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

Warning: Invalid argument supplied for foreach() in /home/admin/public_html/forum/topic.php on line 737
Форумы портала PHP.SU :: помогите с наследованием

 PHP.SU

Программирование на PHP, MySQL и другие веб-технологии
PHP.SU Портал     На главную страницу форума Главная     Помощь Помощь     Поиск Поиск     Поиск Яндекс Поиск Яндекс     Вакансии  Пользователи Пользователи


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

> Без описания
pome
Отправлено: 27 Января, 2012 - 10:31:54
Post Id


Новичок


Покинул форум
Сообщений всего: 17
Дата рег-ции: Май 2011  


Помог: 0 раз(а)




Здравствуйте! Начинаю разбираться с ООП, и вот бьюсь уже не первый день:

задача: создать такой экземпляр клас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 экземпляра родительского класса, то родительский класс не знает методов дочерних классов, в общем я окончательно запутался и зашел в тупик Не понял Помогите пожалуйста разобраться и изящным способом решить задачу Меланхолия
 
 Top
DlTA
Отправлено: 27 Января, 2012 - 11:10:37
Post Id



Постоянный участник


Покинул форум
Сообщений всего: 2952
Дата рег-ции: Окт. 2010  


Помог: 53 раз(а)




Цитата:
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;
...
}

(Отредактировано автором: 27 Января, 2012 - 11:22:40)

 
 Top
Мелкий Супермодератор
Отправлено: 27 Января, 2012 - 11:36:05
Post Id



Активный участник


Покинул форум
Сообщений всего: 11926
Дата рег-ции: Июль 2009  
Откуда: Россия, Санкт-Петербург


Помог: 618 раз(а)




pome, вы совсем не поняли идеи наследования.
Наследование используется, когда у вас главное орудие какое-нибудь и пулемёт. Между ними много общего, это общее объединяют в базовый класс "оружие" и расширяют и конкретизируют в дочерних. Базовый класс зачастую вообще не используется в явном виде нигде.

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

Так, вы создаёте корабль, затем (например, в конструкторе) определяете внутренний член (рационально использовать массив, ведь на корабле не 1 орудие?) оружием (new turrel, являющаяся дочерним классом от weapon), от этого оружия уже получаете его массу и прибавляете его к массе корабля.
В методе shoot корабля вы проверяете, есть ли у него оружие и, если есть, производите выстрел методом уже именно объектом орудия.


-----
PostgreSQL DBA
 
 Top
pome
Отправлено: 27 Января, 2012 - 11:46:58
Post Id


Новичок


Покинул форум
Сообщений всего: 17
Дата рег-ции: Май 2011  


Помог: 0 раз(а)




Цитата:
а зачем пользоваться именно родительским 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. Представленные коды прошу не рассматривать как рабочий код без ошибок, а лишь как пример для того чтобы показать чего я хочу добиться
 
 Top
Самогонщик
Отправлено: 27 Января, 2012 - 12:00:15
Post Id



Посетитель


Покинул форум
Сообщений всего: 495
Дата рег-ции: Окт. 2011  


Помог: 8 раз(а)




pome, создай класс оружия и навешивай его наследников на корабль. То, что в первом посте, совершенно не неверное использование наследования, как и сказал Мелкий.

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

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


Новичок


Покинул форум
Сообщений всего: 17
Дата рег-ции: Май 2011  


Помог: 0 раз(а)




Цитата:
Наследование используется, когда у вас главное орудие какое-нибудь и пулемёт. Между ними много общего, это общее объединяют в базовый класс "оружие" и расширяют и конкретизируют в дочерних. Базовый класс зачастую вообще не используется в явном виде нигде.
Да, видимо не догнал маленько... Хорошо

теперь получается каждый предмет оборудования должен хранить в явном виде 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.  

(Отредактировано автором: 27 Января, 2012 - 12:14:32)

 
 Top
Самогонщик
Отправлено: 27 Января, 2012 - 12:15:47
Post Id



Посетитель


Покинул форум
Сообщений всего: 495
Дата рег-ции: Окт. 2011  


Помог: 8 раз(а)




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] - вот это тут нафиг не нужно

Я писал код, когда твой комментарий был ещё не полный.
 
 Top
pome
Отправлено: 27 Января, 2012 - 12:59:30
Post Id


Новичок


Покинул форум
Сообщений всего: 17
Дата рег-ции: Май 2011  


Помог: 0 раз(а)




Самогонщик
Цитата:
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. }
все объясняет Радость Спасибо большое Закатив глазки
 
 Top
Bio man
Отправлено: 27 Января, 2012 - 14:47:48
Post Id


Постоянный участник


Покинул форум
Сообщений всего: 2751
Дата рег-ции: Июль 2010  
Откуда: Даугавпилс, Латвия


Помог: 52 раз(а)




мне тут одному кажется, что код бредовый? особенно эта часть
pome пишет:
PHP:
скопировать код в буфер обмена
  1. function Weapon->shoot (Ship $target) {
  2. .....
  3. target->set_shoot ($this->power);
 
 Top
Мелкий Супермодератор
Отправлено: 27 Января, 2012 - 15:26:19
Post Id



Активный участник


Покинул форум
Сообщений всего: 11926
Дата рег-ции: Июль 2009  
Откуда: Россия, Санкт-Петербург


Помог: 618 раз(а)




Bio man, за исключением пропущенного $ и Weapon-> не к месту - довольно элегантно получилось связать.
Для правильности можно записать как

PHP:
скопировать код в буфер обмена
  1. function shoot (Ship $target) {
  2. .....
  3. $target->set_shoot ($this->power);


-----
PostgreSQL DBA
 
 Top
Самогонщик
Отправлено: 27 Января, 2012 - 17:08:56
Post Id



Посетитель


Покинул форум
Сообщений всего: 495
Дата рег-ции: Окт. 2011  


Помог: 8 раз(а)




Я просто скопипастил кусок и быстро поправил, думаю автор темы понял, что я имею введу.
 
 Top
pome
Отправлено: 27 Января, 2012 - 18:22:27
Post Id


Новичок


Покинул форум
Сообщений всего: 17
Дата рег-ции: Май 2011  


Помог: 0 раз(а)




Bio man
Цитата:
PS. Представленные коды прошу не рассматривать как рабочий код без ошибок, а лишь как пример для того чтобы показать чего я хочу добиться
 
 Top
Страниц (1): [1]
Сейчас эту тему просматривают: 0 (гостей: 0, зарегистрированных: 0)
« Объектно-ориентированное программирование »


Все гости форума могут просматривать этот раздел.
Только зарегистрированные пользователи могут создавать новые темы в этом разделе.
Только зарегистрированные пользователи могут отвечать на сообщения в этом разделе.
 



Powered by PHP  Powered By MySQL  Powered by Nginx  Valid CSS  RSS

 
Powered by ExBB FM 1.0 RC1. InvisionExBB