Warning: Cannot use a scalar value as an array in /home/admin/public_html/forum/include/fm.class.php on line 757

Warning: Invalid argument supplied for foreach() in /home/admin/public_html/forum/include/fm.class.php on line 770
Форумы портала PHP.SU :: Версия для печати :: помогите с наследованием
Форумы портала PHP.SU » » Объектно-ориентированное программирование » помогите с наследованием

Страниц (1): [1]
 

1. pome - 27 Января, 2012 - 10:31:54 - перейти к сообщению
Здравствуйте! Начинаю разбираться с ООП, и вот бьюсь уже не первый день:

задача: создать такой экземпляр класa Ship, чтобы он имел методы fly() и Shoot(), определенные в классах Weapons и Engines, свойство mass, определенное в классах Weapons и Engines, а Weapons и Engines могли пользоваться свойством ID (типа parent::$ID)
объекта Ship, определенное в его конструкторе.

По-моему должно получиться что-то вроде:

PHP:
скопировать код в буфер обмена
  1.  
  2. class Ship {
  3.         public $ID, $mass = 0;
  4.         function Ship ($ID) {
  5.                 $this->ID = $ID;
  6.         }
  7. }
  8. class Engines extends Ship {
  9.         function Engines () {
  10.                 parent::$mass += 10;
  11.         }
  12.         function fly () {
  13.                 echo "ship ".parent::$ID." flying\n";
  14.         }
  15. }
  16. class Weapons extends Ship {
  17.         function Weapons () {
  18.                 parent::$mass += 20;
  19.         }
  20.         function shoot () {
  21.                 echo "ship ".parent::$ID." shooting\n";
  22.         }
  23. }
  24.  
  25. $ship1 = new Ship (1);
  26. $ship2 = new Ship (2);
  27. $ship1->shoot();        //нужный результат:             ship 1 shooting
  28. $ship2->fly();          //нужный результат:             ship 2 flying
  29. echo $ship1->mass;      //нужный результат:             30
  30.  


Но как я не бьюсь-ничего не выходит, то дочерний класс не знает ID экземпляра родительского класса, то родительский класс не знает методов дочерних классов, в общем я окончательно запутался и зашел в тупик Не понял Помогите пожалуйста разобраться и изящным способом решить задачу Меланхолия
2. DlTA - 27 Января, 2012 - 11:10:37 - перейти к сообщению
Цитата:
function Weapons () {
parent::$mass += 20;
}
это не правильный конструктор
если хотелось чет типа подобного
то надо было у базового объявить __construct($ID=0)
с функционалом function Ship
а у дочерних
__construct($ID=0){
parent::__construct($ID);
parent::$mass += 20;
...
}
как то так

а лучше наверное даже
__construct($ID=0){
parent::__construct($ID);
$this->$mass += 20;
...
}
3. Мелкий - 27 Января, 2012 - 11:36:05 - перейти к сообщению
pome, вы совсем не поняли идеи наследования.
Наследование используется, когда у вас главное орудие какое-нибудь и пулемёт. Между ними много общего, это общее объединяют в базовый класс "оружие" и расширяют и конкретизируют в дочерних. Базовый класс зачастую вообще не используется в явном виде нигде.

А когда что-то включает в себя что-то другое - это ни в коем случае не наследование, это - включение. У корабля есть оружие, но оружие не есть корабль (впрочем, для торпеды это спорное утверждение Подмигивание ).

Так, вы создаёте корабль, затем (например, в конструкторе) определяете внутренний член (рационально использовать массив, ведь на корабле не 1 орудие?) оружием (new turrel, являющаяся дочерним классом от weapon), от этого оружия уже получаете его массу и прибавляете его к массе корабля.
В методе shoot корабля вы проверяете, есть ли у него оружие и, если есть, производите выстрел методом уже именно объектом орудия.
4. pome - 27 Января, 2012 - 11:46:58 - перейти к сообщению
Цитата:
а зачем пользоваться именно родительским ID?
пользуйтесь тем что было наседовано
через $this->ID


Вся идея в том, что объект Ship должен быть единым объектом и иметь в себе много разных методов, которые подключаются "навешиванием" всякого оборудования, и, например, выстрелив, оружие должно отнять у Ship, например, энергию, а у другому экземпляру Ship нанести повреждение. При этом хочется добиться двусторонней связью между наследниками Ship

PHP:
скопировать код в буфер обмена
  1. class Weapons {
  2.         function __construct () {
  3.                 //загружаем параметры оружия пользователя parent::$ID
  4.                 $this->power = -25;
  5.                 $this->energy = -10;
  6.         }
  7.         function shoot ($targetID) {
  8.                 parent::Energy->get_energy ($this->energy);
  9.                 $ship[$targetID]->set_shoot ($this->power);
  10.         }
  11. }
  12.  
  13. $ship[5]->Weapons->shoot (7);   //корабль 5 стреляет в корабль 7
  14.  


PS. Представленные коды прошу не рассматривать как рабочий код без ошибок, а лишь как пример для того чтобы показать чего я хочу добиться
5. Самогонщик - 27 Января, 2012 - 12:00:15 - перейти к сообщению
pome, создай класс оружия и навешивай его наследников на корабль. То, что в первом посте, совершенно не неверное использование наследования, как и сказал Мелкий.

У вас есть два пути:
1. создать наследников оружия с различными параметрами, но наследоваться ради переопределения параметров не круто, проще использовать один класс и настраивать его параметры.
2. Оружие инициализировать указателем на корабль, тогда оно (оружие) сможет совершать с кораблём хитрые манипуляции.

Т.к. во втором случае образуется циклическая ссылка (корабль содержит оружие, оружие ссылается на корабль), Для разрешения цикла, для корабля создаётся интерфейс, с которым и работает оружие ничего не зная о реализации корабля.
(Добавление)
Во втором случае можно будет переопределять поведение, скажем одно оружие просто забирает энергию и наносит урон, а другое стреляет ракетами и требует наличия ракет на складе нужного типа, треть оставляет мину и т.д. Учитывать все эти вариации поведения в классе корабля, не очень хорошо. Проще перенести в оружие, наследники класса оружие могут переопределять метод апдате (к примеру) и вести себя по разному в зависимости от реализации.
6. pome - 27 Января, 2012 - 12:06:25 - перейти к сообщению
Цитата:
Наследование используется, когда у вас главное орудие какое-нибудь и пулемёт. Между ними много общего, это общее объединяют в базовый класс "оружие" и расширяют и конкретизируют в дочерних. Базовый класс зачастую вообще не используется в явном виде нигде.
Да, видимо не догнал маленько... Хорошо

теперь получается каждый предмет оборудования должен хранить в явном виде ID корабля на котором он установлен для того чтобы обращаться к другим предметам этого корабля и делать это через
PHP:
скопировать код в буфер обмена
  1. function Weapon->shoot () {
  2.         global $ship;
  3.         $ship[$this->ownerID]->Energy->get_energy ($this->required_energy)
  4. }


или так:
PHP:
скопировать код в буфер обмена
  1. class Ship {
  2.         function Ship ($ID) {
  3.                 $this->ID = $ID;
  4.                 $this->Weapon = new Weapon ($this->ID);
  5.                 $this->Energy = new Energy ($this->ID);
  6.         }
  7.         function shoot ($targetID) {
  8.                 list($hit, $energy) = $this->Weapon->shoot ();
  9.                 $this->Energy->get_energy ($enrgy);//вот это, по идее, можно было сделать в Weapon->shoot, но тогда нужно иметь ссылку на объект Energy...
  10.                 $ship[$targetID]->set_shoot ($hit);
  11.         }
  12.         function set_shoot ($hit) {
  13.                 $this->hit += $hit;
  14.         }
  15. }
  16.  


Но в этом случае класс Ship будет перегружен кодом, так как частично функционал оборудования нужно будет описывать в самом классе Ship
(Добавление)
Самогонщик То есть вот так будет правильно:?
PHP:
скопировать код в буфер обмена
  1. class Ship {
  2.         function Ship ($ID) {
  3.                 $this->ID = $ID;
  4.                 $this->Weapon = new Weapon ($this);
  5.                 $this->Energy = new Energy ($this);
  6.         }
  7.         function set_shoot ($hit) {
  8.                 $this->hit += $hit;
  9.         }
  10. }
  11. class Weapon {
  12.         function Weapon ($owner) {
  13.                 $this->owner = $owner;
  14.         }
  15.         function shoot ($targetID) {
  16.                 $this->owner->Energy->get_energy ($this->energy);
  17.                 global $ship;
  18.                 $ship[$targetID]->set_shoot ($this->power);
  19.         }
  20. }
  21. $ship[7]->Weapon->shoot (5);
  22.  
7. Самогонщик - 27 Января, 2012 - 12:15:47 - перейти к сообщению
PHP:
скопировать код в буфер обмена
  1. function Weapon->shoot (Ship $target) {
  2.         $this->$ship->Energy->get_energy ($this->required_energy);
  3.         target->set_shoot ($this->power);
  4. }



PHP:
скопировать код в буфер обмена
  1. class Ship {
  2.         function Ship ($ID) {
  3.                 $this->ID = $ID;
  4.                 $this->Weapon = new Weapon (10);
  5.                 $this->Energy = new Energy (100500);
  6.         }
  7.  
  8.         function shoot ($Ship $target) {
  9.                 $this->Weapon->shoot ($target);
  10.         }
  11.  
  12.         function set_shoot ($hit) {
  13.                 $this->hit -= $hit;
  14.         }
  15. }

(Добавление)
global $ship; $ship[$targetID] - вот это тут нафиг не нужно

Я писал код, когда твой комментарий был ещё не полный.
8. pome - 27 Января, 2012 - 12:59:30 - перейти к сообщению
Самогонщик
Цитата:
global $ship; $ship[$targetID] - вот это тут нафиг не нужно
полностью согласен, но не мог понять как Радость но вот это
PHP:
скопировать код в буфер обмена
  1. function Weapon->shoot (Ship $target) {
  2.        $this->$ship->Energy->get_energy ($this->required_energy);
  3.         target->set_shoot ($this->power);
  4.  
  5. }
все объясняет Радость Спасибо большое Закатив глазки
9. Bio man - 27 Января, 2012 - 14:47:48 - перейти к сообщению
мне тут одному кажется, что код бредовый? особенно эта часть
pome пишет:
PHP:
скопировать код в буфер обмена
  1. function Weapon->shoot (Ship $target) {
  2. .....
  3. target->set_shoot ($this->power);
10. Мелкий - 27 Января, 2012 - 15:26:19 - перейти к сообщению
Bio man, за исключением пропущенного $ и Weapon-> не к месту - довольно элегантно получилось связать.
Для правильности можно записать как

PHP:
скопировать код в буфер обмена
  1. function shoot (Ship $target) {
  2. .....
  3. $target->set_shoot ($this->power);
11. Самогонщик - 27 Января, 2012 - 17:08:56 - перейти к сообщению
Я просто скопипастил кусок и быстро поправил, думаю автор темы понял, что я имею введу.
12. pome - 27 Января, 2012 - 18:22:27 - перейти к сообщению
Bio man
Цитата:
PS. Представленные коды прошу не рассматривать как рабочий код без ошибок, а лишь как пример для того чтобы показать чего я хочу добиться

 

Powered by ExBB FM 1.0 RC1