(这个问题使用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的课程terser,但是它可能容易导致错误的,例如

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

当然,人们可能会认为 $myFred->naem 同样会导致错误,这是正确的。但是有一个正式的类只是感觉更硬要我,但是我真的不能证明它。

会有什么优点/缺点使用各种方法和时人们应该使用哪种办法?

有帮助吗?

解决方案

下表面,这两种方法是等效的。但是,您可以使用一个类时,你得到了大多数标准的OO好处:封装,继承等

另外,看看下面的例子:

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

是完全有效的,并可能是一个困难的错误被发现。

在另一方面,

$class->setNaem('John');

将永远不会工作。

其他提示

一个简单的类似这样的:

class PersonalData {
    protected $firstname;
    protected $lastname;

    // Getters/setters here
}

有几个优点过的一个阵列。

  1. 有没有可能使某些拼写错误。 $data['firtsname'] = 'Chris'; 会工作的同时 $data->setFirtsname('Chris'); 会扔en错误。
  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. 我们可以添加一些额外的代码之前set/get操作,例如验证或记录:

    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. 我们可以使用所有的惠益的面向对象就像继承,多态性、类型暗示,封装。
  5. 如前所述,我们所有的"结构"可以继承的一些基类提供了实现 Countable, SerializableIterator 接口,因此,我们的结构可以使用 foreach 循环等等。
  6. IDE支持。

唯一的缺点似乎是速度。创造的一系列和操作上更快。但是我们都知道,在许多情况下存在是便宜得多,程序时间。;)

考虑了一段时间后,这是我自己的答案。

约最主要的过阵列宁愿值对象是<强>清晰度

考虑这样的功能:

// Yes, you can specify parameter types in PHP
function MagicFunction(Fred $fred)
{
    // ...
}

function MagicFunction(array $fred)
{
}

其目的是更清楚。功能作者可以执行他的要求。

更重要的是,作为用户,我可以很容易地查找的什么是有效的弗雷德的。我只需要打开Fred.php,发现其内部。

有是主叫用户和被叫之间的契约。使用值对象,该合同可被写为语法检查代码:

class Fred
{
    public $name;
    // ...
}

如果我使用的阵列,我只希望我的用户会阅读的评论或文档:

// IMPORTANT! You need to specify 'name' and 'age'
function MagicFunction(array $fred)
{
}

根据我可能会使用两种或用例。类的好处是,我可以用它像一个类型和方法或任何自省方法的使用类型提示。如果我只是想周围的一些随机数据集通过从查询或什么的,我想可能使用数组。所以我想只要弗雷德的有在我的模型特殊的意义,我会使用一个类。

在一个旁注:结果 ValueObjects应该是一成不变的。至少如果你指的埃里克·伊文思在领域驱动设计的定义。在福勒的POEA,ValueObjects不一定必须是不可变的(虽然有人建议),但他们不应该有身份,这显然是与本案的弗雷德的。

让我提出这个问题:

有什么不同的关于使一样错字 $myFred['naem'] 和拼写错误喜欢 $myFred->naem?同样的问题仍然存在,在这两种情况下,他们都错误。

我喜欢用 (保持简单,愚蠢)的时候我的节目。

  • 如果你只是返回的一个子集中的查询方法,简单地返回阵列。
  • 如果存储的数据作为 公共/私人/static/保护 变你的一课,它将是最好的储存它作为一个stdClass.
  • 如果你要迟通过这个另类的方法,你可能会喜欢的严格的打字 Fred 类,即 public function acceptsClass(Fred $fredObj)

你可以很容易地创造了一个标准类为反对阵列,如果它是作为回报价值。在这种情况下你不关心的严格的打字。

$class = new stdClass();
$class->param = 'value';
$class->param2 = 'value2';
return $class;

一个用于所述散列亲:这是能够处理的名称 - 值的组合,其在设计时未知

在返回的值表示在应用程序中的实体,您应该使用一个对象,因为这是OOP的目的。如果你只是想返回一组不相关的值,然后它不是那么明确。如果它是一个公共API的一部分,不过,再声明的类仍然是最好的一段路要走。

说实话,我喜欢他们两个。

  • 哈希阵列的方式更快的比让的对象,而时间就是金钱!
  • 但是,JSON不喜欢哈希阵列(其中似乎有点像是面向对象的强迫症)。
  • 也许项目与多个人,一个良好的定义类会更好。
  • 哈希阵列可能需要更多的时间和存储器(一个对象有一个预定的数额),虽然它很难确定每个方案。

但真正很烂的是想使用哪一个太多了。就像我说的,JSON不喜欢哈希。哎呀,我使用一个阵列。我要改变一些万行代码。

我不喜欢这样,但似乎课程中更安全的道路要走。

适当的值对象的好处是没有办法真正让一个无效,并没有办法改变一个存在(诚信“有恒”)。只有getter和类型提示参数,没有办法在编译代码,它可以明显地容易地与可延展的阵列做螺丝它。

或者,也可以在公共构造验证和抛出异常,但是这提供了一个温和的工厂方法。

class Color
{
    public static function create($name, $rgb) {
        // validate both
        if ($bothValid) {
            return new self($name, $rgb);
        } else {
            return false;
        }
    }
    public function getName() { return $this->_name; }
    public function getRgb() { return $this->_rgb; }

    protected function __construct($name, $rgb)
    {
        $this->_name = $name;
        $this->_rgb = $rgb;
    }
    protected $_name;
    protected $_rgb;
}

我与OOP语言超过10年的工作。 如果你了解对象的方式工作,你一定会喜欢它。 继承,多态,封装,超载是OOP的关键优势。 在另一方面,当我们谈论PHP我们要考虑的PHP不是一个全功能的面向对象的语言。 例如,我们不能使用方法重载或构造重载(简单)。

在PHP

关联数组是一个很不错的功能,但我认为危害PHP企业应用程序。 当你写代码,你想获得清洁和维护应用程序。

另一个认为你与关联数组松是不能使用智能感知。

所以,我认为,如果你想写cleanner和更易于维护的代码,你必须使用OOP特性提供时。

我宁愿在你的第二个例子的硬编码属性等。我觉得它更清晰地定义了预期的类结构(和在类的所有可能的属性)。与之相对应的归结为只是始终记得要使用相同的密钥名称的第一个例子。第二种方法,你可以随时回去看看类只是通过查看文件的顶部,以获得性能的想法。

您可以更好地知道自己在做什么毛病第二个 - 如果你尝试echo $this->doesntExist你会得到一个错误,而如果试图echo array['doesntExist']你不会

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top