13

我需要创建大约。5-7个类,每个类将包含很多成员(假设每个类将包含20个成员)。我可以使用公共访问来创建它们,例如:

class A {
    public $myPropertyOne = '';
    public $myPropertyTwo = '';
    ...
}

当然,我更喜欢将这些成员设为私有并为每个属性创建 get/set 方法。IE

class A {
    private $myPropertyOne = '';
    private $myPropertyTwo = '';

    public function getMyPropertyOne() {
            return $this->myPropertyOne;
    }

    public function setMyPropertyOne($myPropertyOne) {
            $this->myPropertyOne = $myPropertyOne;
    }

    public function getMyPropertyTwo() {
            return $this->myPropertyTwo;
    }

    public function setMyPropertyTwo($myPropertyTwo) {
            $this->myPropertyTwo = $myPropertyTwo;
    }
}

但考虑到一个类会有 20 个属性,我将在此之外添加 40 个方法。我在这里担心的是这将如何减慢脚本的速度以及这将需要更多的内存(请记住,我将有几个这样的类)。

另一种解决方案可能是使用魔术函数 __set、__get 但我不想这样做,因为开发 IDE 中的代码完成不会建议对我至关重要的属性。

如果这将是一种编译语言(如 C++),我不会有任何问题,并且会使用带有 getter、setter 的解决方案,但由于 PHP 是解释性语言,我对我的脚本感兴趣,以使用更少的 RAM 并尽可能快。

在此先感谢,对这个问题的任何想法将不胜感激!


我的意见

谢谢大家的回答,我只是想分享我的意见,以防有人会寻找这个问题的答案。

我不能完全同意那些说你不应该关心性能的人,因为这是优化器的任务,我认为这是一个重要因素(至少对我而言),当我们处理 PHP 等解释性语言时,我们将始终必须考虑内存和速度(这一切都让我想起了我为 DOS 开发系统应用程序的时候,呵呵 :) 而且你总是受限于糟糕的 CPU 和千字节的总 RAM,所以如果你能节省额外的钱,你会很高兴byte),在 PHP 开发中,无论添加多少台服务器,您都拥有相同的画面,用户数将始终更高,因此您始终必须决定是否要遵循经典/安全/正确的方法或避免这种情况和在速度或内存方面获得一些收益。

所以....我的观点是,这里最好的方法是对所有成员使用公共访问,并避免对所有属性使用 getter/setter,并使用私有访问和 get/set 方法对需要数据验证或初始化的属性进行访问被设置。

例如:

class B {
    public $myPropertyOne = '';
    public $myPropertyTwo = '';
    private $myPropertyThree = array();


    public function getMyPropertyThree() {
        return $this->myPropertyThree;
    }

    public function setMyPropertyThree($val) {
        if(!is_array($val)) {
            return;
        }

        $this->myPropertyThree = $val;
    }
}

感谢您花时间回答我的问题!

4

6 回答 6

5

简单测试显示实例占用相同数量的内存,不受类中方法数量的影响:

没有方法的类:

class Test1 { }

具有 20 种方法的类:

class Test2 {

    function test1() { return true; }
    function test2() { return true; }
    function test3() { return true; }
    function test4() { return true; }
    function test5() { return true; }
    function test6() { return true; }
    function test7() { return true; }
    function test8() { return true; }
    function test9() { return true; }
    function test10() { return true; }
    function test11() { return true; }
    function test12() { return true; }
    function test13() { return true; }
    function test14() { return true; }
    function test15() { return true; }
    function test16() { return true; }
    function test17() { return true; }
    function test18() { return true; }
    function test19() { return true; }
    function test20() { return true; }

}

测试循环,两个测试相同:

$test = array();
$base = memory_get_usage();
for ($i = 0; $i < 10000; $i++) {
    $test[] = new ClassToBeTested();
}
$used = memory_get_usage() - $base;
print("used: $used\n");

Test1 类的结果(无方法):

used: 3157408

Test2 类的结果(20 种方法):

used: 3157408

我已经在两个单独的脚本中运行它,因为在一个脚本中运行这两个测试显然暴露了一些 PHP 内部分配,并且第二个测试消耗的内存比第一个测试少,无论哪个是第一个或第二个。

虽然您肯定会为实际的类定义占用更多内存,但显然每个类只产生一次成本,而不是每个实例。您不必担心内存使用情况。

于 2012-06-23T07:51:12.087 回答
5

但考虑到一个类将有 20 个属性

拥有这么多属性通常表明信息放错了地方。检查您是否可以将其中一些分组到自己的类中。

除了这个之外,我还有 40 种方法。

一点也不。除非这些类是哑数据结构,否则您不希望它们上有任何 Getter 和 Setter,因为它们会破坏封装。将方法放入您告诉对象执行操作的公共 API 中。

我在这里担心的是这将如何减慢脚本的速度以及这将需要更多的内存(请记住,我将有几个这样的类)。

这不是问题。

另一种解决方案可能是使用魔术函数 __set、__get 但我不想这样做,因为开发 IDE 中的代码完成不会建议对我至关重要的属性。

现代 IDE 可以自动完成魔术方法。

但是,如果您已经在关注微观级别的性能,那么您不需要魔术方法,因为它们肯定会更慢。

除此之外,魔术方法不是 getter 和 setter 的替代品,而是在调用不可访问的属性或方法时触发的错误处理程序。

此外,魔术方法并不明显,并且使 API 难以阅读。

于 2012-06-23T07:52:05.823 回答
1

要使通过魔术方法实现的类的属性被 IDE 突出显示,只需使用@property PHPDoc@property标记,如下所示:

<?php
/**
* @property int id Blog post ID
* @property string title Blog post Title
*/
class Post {

}

更多关于 PHPDoc 的@property 在这里: http: //manual.phpdoc.org/HTMLSmartyConverter/PHP/phpDocumentor/tutorial_tags.property.pkg.html

至于其他问题 - Karoly Horvath 的评论完全涵盖了那些PHP OOP 的很多 setter、getter

于 2012-06-23T08:52:27.937 回答
0

如前所述,你的类应该有这么多属性是很奇怪的。但是,它有时(尽管很少)会发生。但通常,这些属性应该有某种链接在一起:因此您可以将它们存储在哈希图中而不是属性中。然后你只需要一种方法作为吸气剂。

现在,它肯定会消耗更多资源,真的。至于自动完成,请使用常量:您只需键入以下内容:

 $my_class->getFromHashMap($parameter)

并且在键入参数时,您将使用存储在类中的常量:在这里,自动完成应该能够帮助您。

于 2012-06-23T08:16:50.400 回答
0

请记住,我的代码认为属性的名称已以小写形式声明...

  <?php

    class Modelo {
        var $attr1 = "default";
        var $attr2 = 0;


        public function __call($name, $arguments)
        {
            if (method_exists($this, ($method = $name))){
                return $this->$method();
            }
            else{       
                $attribute = split("get",$name);
                if(count($attribute)==2){
                    $attribute = strtolower($attribute[1]);
                    if(isset($this->$attribute)){
                        return ($this->$attribute);
                    }
                }else{
                    $attribute = split("set",$name);
                    if(count($attribute)==2){
                        $attribute = strtolower($attribute[1]);
                        if(isset($this->$attribute) && count($arguments)==1){
                            $this->$attribute=$arguments[0];
                        }else{
                            die("$name number of arguments error: ".join($arguments,","));
                        }
                    }else{
                        die("$name doesn't exist!");
                    }               
                }           
            }
        }


    }

    echo "<pre>";
    $m = new Modelo();
    print_r(
        array(
            "objetct"=>$m
            ,"getAttr1"=>$m->getAttr1()
            ,"getAttr2"=>$m->getAttr2()
        )
    );
    echo "setAttr1\n";
    $m->setAttr1("by set method");
    print_r(
        array(
            "objetct"=>$m
            ,"getAttr1"=>$m->getAttr1()
            ,"getAttr2"=>$m->getAttr2()
        )
    );

    ?>
于 2012-06-23T08:13:23.993 回答
0

你可以试试这个:

特征 get_set {

public function set($what, $value)
{
    $this->{$what} = $value;
}

public function get($what)
{
    return $this->{$what};
}

}

它将适用于公共和受保护的变量。您可以添加 if(!isset($this->{$what})error()

于 2015-05-25T07:24:36.623 回答