Правильное использование классов при наследовании

Обсуждаем, как правильно строить приложения
Ответить
epoxxid
Сообщения: 4
Зарегистрирован: 2017.10.18, 18:27

Правильное использование классов при наследовании

Сообщение epoxxid »

Здравствуйте, уважаемые форумчане!

Хотелось бы услышать мнение сообщества по поводу правильного оформления классов при наследовании.
Чтобы не лить воду, перейду сразу к примеру.
Есть базовый класс:

Код: Выделить всё

<?php
abstract class Animal 
{
	public static function classes()
	{
		return [
			Dog::TYPE_ID => Dog::class,
			Cat::TYPE_ID => Cat::class,
		];
	}

	public function getTypeId()
	{
		return static::TYPE_ID;
	}
	
	public function getTypeAlias()
	{
		return static::TYPE_ALIAS;
	}
	
	public function getTypeTitle()
	{
		return static::TYPE_TITLE;
	}
}
Есть классы-наследники:

Код: Выделить всё

<?php
class Dog extends Animal 
{
	const TYPE_ID = 1;
	const TYPE_ALIAS = 'dog';
	const TYPE_TITLE =' Собака';
	
	// Dog related methods
	public function sayWoof() {}
}
class Cat extends Animal
{
	const TYPE_ID = 2;
	const TYPE_ALIAS = 'cat';
	const TYPE_TITLE = 'Кошка';
	
	// Cat related methos
	public function sayMeow() {}
}
То есть, допустим, у нас есть некий журнал учета животных в приюте. Все записи о животных хранятся в одной таблице БД. В этой таблице есть поле INT `type_id`, в котором хранится тип животного и на основе которого, при извлечении данных, инстанцируются соответствующие классы (Single Table Inheritance).

Так вот, собственно, что меня смутило. Я использовал константы для определения свойств в дочерних классах - вроде бы свойства классов постоянные и неизменяемые, НО:
1. В абстрактном классе Animal, PhpStorm ругается - мол, нет таких констант в данном классе. Добавление констант-пустышек, только лишь бы удовлетворить IDE, кажется не очень хорошей идеей.
2. Иногда, при использовании констант для таких целей, получается их переопределение (override) в дочерних классах, а это тоже, как я читал на StackOverflow, не очень хорошая практика. Типа константа должна быть константой).

Но есть и определенные плюсы:
1. Можно обратиться к свойствам классов без создания экземпляра. Например, чтобы получит список классов всех видов животных в БД (как в методе Animal::classes()).
2. Константы не 'висят' в самом экземпляре класса, например если сделать

Код: Выделить всё

var_dump(new Dog())
, в отличии от свойств класса. Может, даже, это как-то поможет в экономии памяти если свойств много (я предполагаю из сравнения с prototype в JS).
3. Для глаза как-то чище и приятнее код.

Расскажите свое мнение по этому поводу. Может лучше использовать статические свойства? Или можете предложить свои примеры решения таких ситуаций?
zelenin
Сообщения: 10596
Зарегистрирован: 2013.04.20, 11:30

Re: Правильное использование классов при наследовании

Сообщение zelenin »

epoxxid писал(а): 2017.10.18, 19:09Так вот, собственно, что меня смутило. Я использовал константы для определения свойств в дочерних классах - вроде бы свойства классов постоянные и неизменяемые, НО:
1. В абстрактном классе Animal, PhpStorm ругается - мол, нет таких констант в данном классе. Добавление констант-пустышек, только лишь бы удовлетворить IDE, кажется не очень хорошей идеей.
2. Иногда, при использовании констант для таких целей, получается их переопределение (override) в дочерних классах, а это тоже, как я читал на StackOverflow, не очень хорошая практика. Типа константа должна быть константой).

Но есть и определенные плюсы:
1. Можно обратиться к свойствам классов без создания экземпляра. Например, чтобы получит список классов всех видов животных в БД (как в методе Animal::classes()).
2. Константы не 'висят' в самом экземпляре класса, например если сделать

Код: Выделить всё

var_dump(new Dog())
, в отличии от свойств класса. Может, даже, это как-то поможет в экономии памяти если свойств много (я предполагаю из сравнения с prototype в JS).
3. Для глаза как-то чище и приятнее код.

Расскажите свое мнение по этому поводу. Может лучше использовать статические свойства? Или можете предложить свои примеры решения таких ситуаций?
ты столько писал, чтобы не сказать главного - на какие константы ругается PS?
epoxxid
Сообщения: 4
Зарегистрирован: 2017.10.18, 18:27

Re: Правильное использование классов при наследовании

Сообщение epoxxid »

В абстрактном классе нет констант TYPE_ID, TYPE_ALIAS и TYPE_TITLE. На их отсутствие ругается PhpStorm.
Я даже не столько об этом хотел сказать, сколько хотел узнать мнение о том, допустим ли такой вообще подход, с указанием параметров классов в константах и переопределения этих констант в классах-наследниках?
zelenin
Сообщения: 10596
Зарегистрирован: 2013.04.20, 11:30

Re: Правильное использование классов при наследовании

Сообщение zelenin »

конечно не допустим. нет констант, а, значит, нет никакой информации, что они будут в наследниках. PS правильно ругается.
В твоем случае методы абстрактного класса должны быть абстрактными и не важно реализуются ли они в наследниках через константы или нет.
Методы в абстрактном классе дают информацию, что эти методы будут в наследниках.
epoxxid
Сообщения: 4
Зарегистрирован: 2017.10.18, 18:27

Re: Правильное использование классов при наследовании

Сообщение epoxxid »

Тогда, получается, самое универсальное решение: я определяю для таких целей в абстрактном классе абстрактные статические методы и реализую их в классах наследниках. Это и кода меньше потребует, и позволит одновременно получить доступ к этим свойствам и из статического (Cat::getAlias()) и из динамического ((new Cat())->getAlias()) контекста. Правильно?
Аватара пользователя
maleks
Сообщения: 1985
Зарегистрирован: 2012.12.26, 12:56

Re: Правильное использование классов при наследовании

Сообщение maleks »

epoxxid писал(а): 2017.10.19, 10:02 я определяю для таких целей в абстрактном классе абстрактные статические методы и реализую их в классах наследниках.
Не верно, да и не сможете сделать статический метод абстрактным.
Yii2 universal module sceleton - for basic and advanced templates
zelenin
Сообщения: 10596
Зарегистрирован: 2013.04.20, 11:30

Re: Правильное использование классов при наследовании

Сообщение zelenin »

не используйте статические методы и свойства.
epoxxid
Сообщения: 4
Зарегистрирован: 2017.10.18, 18:27

Re: Правильное использование классов при наследовании

Сообщение epoxxid »

zelenin писал(а): 2017.10.19, 10:42 не используйте статические методы и свойства.
А как тогда быть со свойствами, которые одинаковы для всех экземпляров данного класса и должны быть доступны как из статического, так и из динамического контекста?
zelenin
Сообщения: 10596
Зарегистрирован: 2013.04.20, 11:30

Re: Правильное использование классов при наследовании

Сообщение zelenin »

epoxxid писал(а): 2017.10.19, 16:31
zelenin писал(а): 2017.10.19, 10:42 не используйте статические методы и свойства.
А как тогда быть со свойствами, которые одинаковы для всех экземпляров данного класса и должны быть доступны как из статического, так и из динамического контекста?
понимаете, вы изначально манипулируете, ставя некорректный вопрос.

- тупые ножи не нужны.
- но как быть в ситуациях, когда нужны тупые ножи?

Получается, что тупой нож вам действительно нужен, раз у вас возникают такие ситуации.
Но может быть в вашей ситуации нужен не тупой нож, а острый? или вообще отвертка? или просто не попадать в такие ситуации?
Ответить