A simple array data structure implementation in PHP, version 3
In previous versions of one dimentional array data structure in PHP programming language, we developed a data structure called AbstractOneDimArray
and used ArrayAccess
interface to use [] operator in our array data structure.
In this version, we make more from interface concept and also use a new tool. In fact we are going to use a famous design pattern called Factory. We implmented a factory to use in our array data strucrue execution test.
We also derive two other concrete calsses FloatOneDimArray
and StringOneDimArray
from our base class.
The first step is how to use interface concept. We implement an interface to force array data structures to implement Size
method.
interface OneDimArrayInterface
{
function __construct(int $size);
function Size(): int;
}
Then in our case, we use this interface as well.
abstract class AbstractOneDimArray implements OneDimArrayInterface, \ArrayAccess
You noticed that we used two interface at the same time. This is valid in PHP and is very helpful also.
The base class implementation remains untouched despite this tiny change.
Now, we are going to implement more simple arrays, for float data type and string data type as well.
class FloatOneDimArray extends AbstractOneDimArray
{
protected function getValueType() : string
{
return gettype(1.0);
}
protected function getDefaultValue()
{
return 0.0;
}
}
class StringOneDimArray extends AbstractOneDimArray
{
protected function getValueType() : string
{
return gettype('');
}
protected function getDefaultValue()
{
return '';
}
}
One again, you see that we need only to implement two methods: getValueType
and getDefaultValue
. This is the power of OOP (object-oriented programming).
Now, as we promised, we are going to use factory design pattern to make neater execution test. We implement OneDimArrayFactory
class like this:
class OneDimArrayFactory
{
public static function Make(string $type, int $size)
{
switch ($type)
{
case 'int':
case 'integer':
return new IntOneDimArray($size);
break;
case 'float':
case 'double':
return new FloatOneDimArray($size);
break;
case 'string':
default:
return new StringOneDimArray($size);
// throw new Exception('OneDimArray is not implemented for the type ' . $type);
break;
}
}
}
Now, our execution test for int array turns into this code:
$size = 5;
$intArray = OneDimArrayFactory::Make(gettype(0), $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];
Even neater and more beautiful from the last one, yeah? We keep track of making our code more professional in the next versions.
Code
<?php
namespace Techanic\CS\DS\Linear\Vector;
use Exception;
interface OneDimArrayInterface
{
function __construct(int $size);
function Size(): int;
}
abstract class AbstractOneDimArray implements OneDimArrayInterface, \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;
}
}
class FloatOneDimArray extends AbstractOneDimArray
{
protected function getValueType() : string
{
return gettype(1.0);
}
protected function getDefaultValue()
{
return 0.0;
}
}
class StringOneDimArray extends AbstractOneDimArray
{
protected function getValueType() : string
{
return gettype('');
}
protected function getDefaultValue()
{
return '';
}
}
class OneDimArrayFactory
{
public static function Make(string $type, int $size)
{
switch ($type)
{
case 'int':
case 'integer':
return new IntOneDimArray($size);
break;
case 'float':
case 'double':
return new FloatOneDimArray($size);
break;
case 'string':
default:
return new StringOneDimArray($size);
// throw new Exception('OneDimArray is not implemented for the type ' . $type);
break;
}
}
}
$size = 5;
$intArray = OneDimArrayFactory::Make(gettype(0), $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];