我正在努力让以下工作,但我不知所措......
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的新实例吗?或者我错过了什么?
提前感谢您的帮助。
答案 0 :(得分: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 请务必阅读所有内容,如果OO对您而言可能需要几次。
答案 1 :(得分:1)
bar有一个名为somethingelse的成员变量,它继承自foo。
你正在混合对象和类范围。
如果你真的想要实现所描述的效果,你必须使你的变量变为静态,所以它的上下文是基于类的
答案 2 :(得分:0)
首先,您必须区分静态变量和实例变量。静态变量在类的所有实例之间共享,实例变量不是。
如果你希望Foo和Bar的每个实例都具有完全相同的SomethingElse-Instance,你必须使$ somethingelse静态:
public static $ somethingelse
你应该改变Foo的作文功能:
function composition() {
self::$somethingelse = new SomethingElse();
}
要访问此静态字段,您可以执行以下操作: $ foo = new Foo(); //我是Foo $ foo->组合物(); //我是其他班级 FOO:$ somethingelse->测试(); //我是SomethingElse类中的一个方法
$ bar = new Bar(); //我是Bar,我的父母是Foo 酒吧:: $ somethingelse->测试(); //我是SomethingElse类中的一个方法
如果您希望Foo和Bar的每个实例都有自己的SomethingElse实例,您可以使用您的代码,但是您需要添加
$酒吧,>组合物()
在$ bar-> somethingelse-> test();
之前那是因为
$ bar = new Bar();
您创建了一个全新的Bar实例,该实例具有$ somethingelse属性,但尚未设置。所以你需要调用composition()来设置它。
如果每个Foo和Bar应该具有完全相同的SomethingElse-instance,则应该使用静态版本,因为它减少了所需的内存。
我希望这可以帮到你。否则我很乐意进一步解释。
答案 3 :(得分: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 = new Person(); $ me-> firstName =“Thomas”
$ princeCharles = new Royalty();
你不希望$ princeCharles的firstName属性等于“Thomas”,如果你想设置$ princeCharles-> firstName,你不要改变$ firstName属性的值。我
$ me和$ princeCharles都有一个属性'firstName',但我们不共享该属性的值。
答案 4 :(得分:0)
我认为如果在派生类构造函数中调用父类构造函数,您的问题将得到解决。默认情况下,这在PHP中不会发生,因此在遇到继承数据成员的问题时请记住这一点。
类Bar延伸Foo { public function __construct(){ 父:: __构建体();
}
}