یک پیادهسازی از دادهساختار آرایهی ساده در پیاچپی (PHP)، نسخه ۲
در نسخه قبلی دادهساختار آرایهی یکبعدی در زبان برنامهنویسی پیاچپی (PHP)، ما یک دادهساختار ساده برای اضافه کردن پشتیبانی از آرایهی ساده به پیاچپی (PHP) ایجاد کردیم. اما همانطور که ممکن است متوجه شده باشید، ما تلاش کردیم از هر گونه ویژگی پیشرفتهی پیاچپی (PHP) استفاده نکنیم.
در این مقاله از یک ویژگی دوستداشتنی در پیاچپی (PHP) استفاده میکنیم تا پیادهسازی خود را تمیزتر کنیم. قبل از آن، ما متدهای Getter و Seter را با استفاده از متدهای عمومی Get
و Set
پیادهسازی کردیم. اما این شبیه آرایههای معمولی در بسیاری از زبانهای برنامهنویسی نیست. ما دوست داریم اپراتور [] مانند "C" داشته باشیم.
خوشبختانه، یک ویژگی خوب در پیاچپی (PHP) به ما کمک میکند تا چنین چیزی را به کلاس خود اضافه کنیم. اینترفیس ArrayAccess
چهار متد برای این کار اعلان میکند. ابتدا باید تعریف کلاس خود را به این صورت تغییر دهیم:
abstract class AbstractOneDimArray implements \ArrayAccess
بنابراین ما عملیات اینترفیس را پیادهسازی میکنیم. اولین متد offsetExists
است:
public offsetExists(mixed $offset): bool
این متد (همانطور که نامش نشان میدهد) برای بررسی این که آیا یک اندیس در آرایه وجود دارد یا نه، استفاده میشود. پیادهسازی ما برای این متد به این شکل است:
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);
}
دومین متد offsetGet
است که متد getter ما را جایگزین میکند.
public offsetGet(mixed $offset): mixed
پیادهسازی متد getter ما به این صورت تغییر میکند:
public function offsetGet($index)
{
if (gettype($index) != gettype(0))
throw new Exception('The index must be of type ' . gettype(0));
return $this->_values[$index];
}
متد دیگر offsetSet
است که متد setter ما را جایگزین میکند.
public offsetSet(mixed $offset, mixed $value): void
پیادهسازی setter ما به این صورت تغییر میکند:
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;
}
و متد آخر offsetUnset
است که برای حذف یک آیتم از آرایه به کار برده میشود، هنگامی که PHP به کد unset()
برخورد میکند.
public offsetSet(mixed $offset, mixed $value): void
پیادهسازی ما به این شکل تغییر میکند:
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();
}
اکنون میتوانیم پیادهسازی خود را به این صورت تست کنیم:
$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];
این کد تمیزتر و زیباتر نیست؟
کد
<?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];