【问题标题】:PHP5 Classes: inheriting a composed class?PHP5 类:继承一个组合类?
【发布时间】:2009-06-12 16:28:32
【问题描述】:

我正试图让以下工作,但我不知所措......

class Foo {
    public $somethingelse;

    function __construct() {
        echo 'I am Foo';
    }
    function composition() {
        $this->somethingelse =& new SomethingElse();
    }
}
class Bar extends Foo {
    function __construct() {
        echo 'I am Bar, my parent is Foo';
    }
}
class SomethingElse {
    function __construct() {
        echo 'I am some other class';
    }
    function test() {
        echo 'I am a method in the SomethingElse class';
    }
}

我想做的是在 Foo 类中创建 SomethingElse 类的实例。这使用=& 有效。但是当我用类Bar扩展类Foo时,我认为子类继承了父类的所有数据属性和方法。但是,$this->somethingelse 似乎在子类 Bar 中不起作用:

$foo = new Foo(); // I am Foo
$foo->composition(); // I am some other class
$foo->somethingelse->test(); // I am a method in the SomethingElse class

$bar = new Bar(); // I am Bar, my parent is Foo
$bar->somethingelse->test(); // Fatal error: Call to a member function test() on a non-object

那么,就不能这样继承吗?如果我想在那里使用它,我应该从类 Bar 中创建一个新的类 SomethingElse 实例吗?还是我错过了什么?

提前感谢您的帮助。

【问题讨论】:

  • 您正在继承类 Foo,而不是您创建的类 Foo 的实例,它设置了其他内容。
  • 如果您将 SomethingElse 设为单例,那么您将使用 SomethingElse::getInstance() 而不是构造函数——否则在任意两个实例之间,SomethingElse 实例将有所不同。

标签: php inheritance composition


【解决方案1】:

我以为子类继承了父类的所有数据属性和方法。

这是真的——子类继承父类的静态变量和静态方法。此外,任何子对象都将继承静态和实例变量和方法。

利用现有的类结构获得所需的一种可能性是:

$bar = new Bar();
$bar->composition();// here you are calling the parent method, sets instance var $somethineelse
$bar->somethingelse->test();// now you can call methods

在子实例中完成继承变量(在本例中为对象)的另一种方法如下:

class Foo {
    protected $somethingelse;
    public function __construct() {
        $this->somethingelse = new SomethingElse();
    }
}

class Bar extends Foo {
    public function __construct() {
        parent::__construct();
        // now i've got $somethingelse
    }
 }

为了更好地了解 PHP 5 中的类和对象,请看这里: http://php.net/manual/en/language.oop5.php 确保通读一遍,如果 OO 对您来说是新的,也许可以读几遍。

【讨论】:

    【解决方案2】:

    bar 有一个名为 somethingelse 的成员变量,它继承自 foo。

    您正在混合对象和类范围。

    如果你真的想达到描述的效果,你必须让你的变量静态,所以它的上下文是基于类的

    【讨论】:

      【解决方案3】:

      首先,您必须区分静态变量和实例变量。静态变量在类的所有实例之间共享,而实例变量则不是。

      如果您希望 Foo 和 Bar 的每个实例都具有完全相同的 SomethingElse-Instance,则必须将 $somethingelse 设为静态:

      公共静态 $somethingelse

      你应该改变 Foo 的组合函数:

      function composition() {
          self::$somethingelse = new SomethingElse();
      }
      

      要访问此静态字段,您可以执行以下操作: $foo = 新的 Foo(); //我是福 $foo->composition(); // 我是其他班级 Foo:$somethingelse->test(); // 我是SomethingElse类中的一个方法

      $bar = new Bar(); // 我是 Bar,我的父母是 Foo 酒吧::$somethingelse->test(); // 我是SomethingElse类中的一个方法

      如果您希望 Foo 和 Bar 的每个实例都有自己的 SomethingElse 实例,您可以使用您的代码,但您需要添加

      $bar->composition()

      $bar->somethingelse->test() 之前;

      那是因为

      $bar = new Bar();

      您创建了一个全新的 Bar 实例,该实例具有 $somethingelse 属性,但尚未设置。所以需要调用 composition() 来设置。

      如果每个 Foo 和 Bar 都应该具有完全相同的 SomethingElse 实例,则应该改用静态版本,因为它减少了所需的内存。

      我希望这可以帮助你。否则我很乐意进一步解释。

      【讨论】:

        【解决方案4】:

        说类共享属性并不意味着对象共享属性值

        正如其他人所指出的,您将类与实例混淆了。

        注意,如果你这样做了,你会得到同样的错误:

        $foo = new Foo(); // I am Foo
        $foo->composition(); // I am some other class
        $foo->somethingelse->test(); // I am a method in the SomethingElse class
        
        $foo2 = new Foo(); // I another Foo
        $foo2->somethingelse->test(); // Fatal error: Call to a member function test() on a non-object
        

        不那么抽象地考虑类。例如,您可能有一个类“Person”,它是“Royalty”的父类。

        如果你这样做了:

        $me = new Person(); $me->firstName = "托马斯"

        $princeCharles = 新版税();

        你不希望 $princeCharles 的 firstName 属性等于“Thomas”,如果你想设置 $princeCharles->firstName,你不需要改变 $me 的 firstName 属性的值.

        $me 和 $princeCharles 都有一个属性“firstName”,但我们不共享该属性的

        【讨论】:

          【解决方案5】:

          如果在派生类构造函数中调用父类构造函数,我认为你的问题将得到解决。这在 PHP 中默认不会发生,因此当您在继承数据成员方面遇到问题时请记住这一点。

          类 Bar 扩展 Foo { 公共函数 __construct() { 父级::__construct();

          }
          

          }

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2019-02-08
            • 2012-08-10
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2014-11-22
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多