PHP 中的值对象与关联数组

2022-08-30 12:14:10

(这个问题使用PHP作为上下文,但不仅限于PHP,例如,任何具有内置哈希的语言也是相关的)

让我们看一下这个例子(PHP):

function makeAFredUsingAssoc()
{
    return array(
        'id'=>1337,
        'height'=>137,
        'name'=>"Green Fred");
}

对:

class Fred
{
    public $id;
    public $height;
    public $name;

    public function __construct($id, $height, $name)
    {
        $this->id = $id;
        $this->height = $height;
        $this->name = $name;
    }
}

function makeAFredUsingValueObject()
{
    return new Fred(1337, 137, "Green Fred");
}

方法#1当然更简洁,但它很容易导致错误,例如

$myFred = makeAFredUsingAssoc();
return $myFred['naem']; // notice teh typo here

当然,有人可能会争辩说,这同样会导致错误,这是事实。然而,拥有一个正式的课程对我来说只是感觉更僵化,但我无法真正证明它。$myFred->naem

使用每种方法的利弊是什么,人们什么时候应该使用哪种方法?


答案 1

在表面上,这两种方法是等效的。但是,使用类时,您可以获得大多数标准 OO 优势:封装、继承等。

另外,请查看以下示例:

$arr['naem'] = 'John';

是完全有效的,并且可能是一个难以找到的错误。

另一方面

$class->setNaem('John');

永远不会工作。


答案 2

像这样的简单类:

class PersonalData {
    protected $firstname;
    protected $lastname;

    // Getters/setters here
}

与阵列相比,几乎没有什么优势。

  1. 不可能做一些错别字。 将工作,而将抛出 en 错误。$data['firtsname'] = 'Chris';$data->setFirtsname('Chris');
  2. 类型提示:PHP数组可以包含所有内容(包括任何内容),而定义良好的类仅包含指定的数据。

    public function doSth(array $personalData) {
        $this->doSthElse($personalData['firstname']); // What if "firstname" index doesn't exist?
    }
    
    
    public function doSth(PersonalData $personalData) {
        // I am guaranteed that following method exists. 
        // In worst case it will return NULL or some default value
        $this->doSthElse($personalData->getFirstname());
    }
    
  3. 我们可以在设置/获取操作之前添加一些额外的代码,例如验证或日志记录:

    public function setFirstname($firstname) {
        if (/* doesn't match "firstname" regular expression */) {
            throw new InvalidArgumentException('blah blah blah');
        }
    
    
    
    if (/* in debbug mode */) {
        log('Firstname set to: ' . $firstname);
    }
    
    
    $this->firstname = $firstname;
    
    }
  4. 我们可以使用OOP的所有优点,如继承,多态性,类型提示,封装等...
  5. 如前所述,我们所有的“结构”都可以从一些为 或接口提供实现的基类继承,因此我们的结构可以使用循环等。CountableSerializableIteratorforeach
  6. 集成开发环境支持。

唯一的缺点似乎是速度。创建阵列并对其进行操作的速度更快。但是我们都知道,在许多情况下,CPU时间比程序员时间便宜得多。;)


推荐