Классы PHP5: наследование составного класса? - PullRequest
0 голосов
/ 12 июня 2009

Я пытаюсь заставить работать следующее, но я в растерянности ...

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';
    }
}

Что я хотел бы сделать, так это создать экземпляр класса SomethingElse внутри класса Foo. Это работает с использованием =&. Но когда я расширил класс Foo классом Bar, я подумал, что ребенок наследует все атрибуты данных и методы родительского класса. Однако, кажется, что $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

Итак, нельзя ли наследовать таким образом? И должен ли я создать новый экземпляр класса SomethingElse из класса Bar, если я хочу использовать его там? Или я что-то упустил?

Заранее спасибо за помощь.

Ответы [ 5 ]

5 голосов
/ 12 июня 2009

Я думал, что ребенок наследует все атрибуты данных и методы из родительского класса.

Это правда - дочерний класс наследует статические переменные и статические методы от родительского класса. Кроме того, любые дочерние объекты будут наследовать статические переменные и переменные экземпляра и методы.

Одна из возможностей получить то, что вы хотите с помощью существующей структуры классов, такова:

$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 голос
/ 12 июня 2009

bar имеет переменную-член с именем Someelse, которая унаследована от foo.

вы смешиваете объект и область видимости.

если вы действительно хотите добиться описанного эффекта, вы должны сделать вашу переменную статической, чтобы ее контекст основывался на классе

0 голосов
/ 13 июня 2009

Я думаю, что ваша проблема будет решена, если в производном классе конструктор вызовет родительский класс конструктора. Это не происходит по умолчанию в PHP, поэтому имейте это в виду, когда возникают проблемы с наследованием элементов данных.

класс Бар расширяет Foo { публичная функция __construct () { Родитель :: __ конструкт ();

}

}

0 голосов
/ 13 июня 2009

Утверждение, что классы имеют общие атрибуты, не означает, что объекты разделяют значения атрибутов .

Как уже отмечали другие, вы путаете классы с экземплярами.

Обратите внимание, вы получите ту же ошибку, если вы сделали:

$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 .

И $ me, и $ princeCharles имеют атрибут firstName, но мы не разделяем значение этого атрибута.

0 голосов
/ 12 июня 2009

Во-первых, вы должны различать статические и переменные экземпляра. Статические переменные являются общими для всех экземпляров класса, переменные экземпляров - нет.

Если вы хотите, чтобы у каждого экземпляра Foo и Bar был один и тот же экземпляр SomethingElse-Instance, вы должны сделать $ кое-что статичным:

общедоступная статическая $ someelse

и вам следует изменить композиционную функцию Foo:

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

Для доступа к этому статическому полю вы можете сделать следующее: $ foo = new Foo (); // Я Фу $ Foo-> композиция (); // я другой класс Foo: $ somethingelse-> тест (); // Я метод в классе SomethingElse

$ bar = new Bar (); // Я Бар, мой родитель Foo Bar :: $ somethingelse-> тест (); // Я метод в классе SomethingElse

Если вы хотите, чтобы у каждого экземпляра Foo и Bar был свой экземпляр SomethingElse, вы можете использовать свой код, но вам нужно добавить

$ бар-> композиция ()

перед $ bar-> somethingelse-> test ();

Это потому, что с

$ bar = new Bar ();

вы создали совершенно новый экземпляр Bar, и этот экземпляр имеет свойство $thingelse, но оно еще не установлено. Поэтому вам нужно вызвать состав (), чтобы установить его.

Если у каждого Foo и Bar должен быть один и тот же экземпляр SomethingElse, вам следует вместо этого использовать статическую версию, поскольку она уменьшает необходимую память.

Надеюсь, это поможет вам. В противном случае я очень рад объяснить это дальше.

...