0

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

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 实例吗?还是我错过了什么?

在此先感谢您的帮助。

4

5 回答 5

5

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

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

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

$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为你。

于 2009-06-12T16:51:14.687 回答
1

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

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

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

于 2009-06-12T16:35:02.510 回答
0

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

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

公共静态 $somethingelse

你应该改变 Foo 的组合功能:

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

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

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

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

$bar->composition()

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

那是因为与

$bar = 新的 Bar();

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

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

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

于 2009-06-12T17:21:00.327 回答
0

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

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

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

$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 = 新人();$me->firstName = "托马斯"

$princeCharles = 新版税();

您不希望 $princeCharles 的 firstName 属性等于“Thomas”,并且如果您想设置 $princeCharles->firstName,您不需要更改 $me 的 firstName 属性的值。

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

于 2009-06-12T20:05:29.150 回答
0

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

类 Bar 扩展 Foo { public function __construct() { parent::__construct();

}

}

于 2009-06-12T20:19:01.240 回答