A simple array data structure implementation in PHP, version 2
In the previous version of one dimentional array data structure in PHP programming language, we developed a simple data structure to add support for simple array in PHP. But as you may noticed, we tries not to use any advanced feature of PHP.
In this article we use a lovely feature in PHP to make our implementation neater. Before, we used to implement getter and setter methods with public methods Get
and Set
, but that is not much like normal array in many programming languages. We like to have the [] operator like in C
.
Fortunately, there is a nice feature in PHP help us to add such a thing to our class. The interface ArrayAccess
has four method declaratoin for this. First we need to change our class definition like this:
abstract class AbstractOneDimArray implements \ArrayAccess
Then we implement the interface operations, the first one is offsetExists
:
public offsetExists(mixed $offset): bool
This method used (as it's name shows) to check whether an index exists in the array or not. Our implemention for this method is like this:
public function offsetExists($index)
{
if (gettype($index) != gettype(0))
throw new Exception('The index must be of type ' . gettype(0));
return ($index >=0 && $index < $this->_size);
}
The second method is offsetGet
that replaces our getter method.
public offsetGet(mixed $offset): mixed
Our getter implementation changes to:
public function offsetGet($index)
{
if (gettype($index) != gettype(0))
throw new Exception('The index must be of type ' . gettype(0));
return $this->_values[$index];
}
The other method is offsetSet
that replaces our setter method.
public offsetSet(mixed $offset, mixed $value): void
Our setter implementation changes to:
public function offsetSet($index, $value)
{
if (gettype($index) != gettype(0))
throw new Exception('The index must be of type ' . gettype(0));
if ($index = $this->_size)
throw new Exception('The index must be in the range (0, ' . ($this->_size -1) . ')');
if (gettype($value) != $this->getValueType())
throw new Exception('The value must be of type ' . $this->getValueType());
$this->_values[$index] = $value;
}
And the last method is offsetUnset
used to remove an item from the array and fired whenever PHP encounter a usage of unset()
method.
public offsetSet(mixed $offset, mixed $value): void
Our implementation changes to:
public function offsetUnset($index)
{
if (gettype($index) != gettype(0))
throw new Exception('The index must be of type ' . gettype(0));
if ($index = $this->_size)
return;
$this->_values[$index] = $this->getDefaultValue();
}
Now, we could test our implementation like this:
$size = 5;
$intArray = new IntOneDimArray($size);
for ($i = 0; $i Size(); $i++) {
echo $intArray[$i] . ', ';
}
echo PHP_EOL;
for ($i = 0; $i Size(); $i++) {
$intArray[$i] = $i;
}
for ($i = 0; $i Size(); $i++) {
echo $intArray[$i] . ', ';
}
echo PHP_EOL;
echo $intArray[$size];
Isn't this neater and more beautiful?
Code
<?php
namespace Techanic\CS\DS\Linear\Vector;
use Exception;
abstract class AbstractOneDimArray implements \ArrayAccess
{
/**
*
* @var int
*/
protected /*int*/ $_size = 0;
/**
*
* @var array
*/
protected /*array*/ $_values = [];
protected abstract function getValueType() : string;
protected abstract function getDefaultValue();
public function __construct(int $size)
{
if ($size < 0)
throw new Exception('Size must be positive number.');
$this->_size = $size;
$defaultValue = $this->getDefaultValue();
if (gettype($defaultValue) != $this->getValueType())
throw new Exception('Return type of the getDefaultValue() does not match getValueType().');
for ($i = 0; $i < $this->_size; $i++)
$this->_values[$i] = $defaultValue;
}
public function Size() : int
{
return $this->_size;
}
public function offsetSet($index, $value)
{
if (gettype($index) != gettype(0))
throw new Exception('The index must be of type ' . gettype(0));
if ($index < 0 || $index >= $this->_size)
throw new Exception('The index must be in the range (0, ' . ($this->_size -1) . ')');
if (gettype($value) != $this->getValueType())
throw new Exception('The value must be of type ' . $this->getValueType());
$this->_values[$index] = $value;
}
public function offsetExists($index)
{
if (gettype($index) != gettype(0))
throw new Exception('The index must be of type ' . gettype(0));
return ($index >=0 && $index < $this->_size);
}
public function offsetGet($index)
{
if (gettype($index) != gettype(0))
throw new Exception('The index must be of type ' . gettype(0));
return $this->_values[$index];
}
public function offsetUnset($index)
{
if (gettype($index) != gettype(0))
throw new Exception('The index must be of type ' . gettype(0));
if ($index < 0 || $index >= $this->_size)
return;
$this->_values[$index] = $this->getDefaultValue();
}
}
class IntOneDimArray extends AbstractOneDimArray
{
protected function getValueType() : string
{
return gettype(0);
}
protected function getDefaultValue()
{
return 0;
}
}
$size = 5;
$intArray = new IntOneDimArray($size);
for ($i = 0; $i < $intArray->Size(); $i++) {
echo $intArray[$i] . ', ';
}
echo PHP_EOL;
for ($i = 0; $i < $intArray->Size(); $i++) {
$intArray[$i] = $i;
}
for ($i = 0; $i < $intArray->Size(); $i++) {
echo $intArray[$i] . ', ';
}
echo PHP_EOL;
echo $intArray[$size];