Вообще, это плохой знак для хранения разных типов в списке?

Итак, давайте приведем список:

class A
{
public function methodA() { }
}

class B
{
public function methodB() { }
}

$list = [];
$list[] = new A();
$list[] = new A();
$list[] = new B();

или с общим типом:

abstract class C
{
public function methodC() { }
}

class A extends C
{
public function methodA() { }
}

class B extends C
{
public function methodB() { }
}

$list = [];
// at least $list elements are instanceof C
$list[] = new A();
$list[] = new A();
$list[] = new B();

главная проблема всякий раз, когда я хочу использовать methodB()Я должен убедиться, что его B основан. Все это может относиться к Java: мы должны постоянно приводить / использовать гереники.
Я знаю, что в классическом массиве хранятся элементы одного типа. Это относится к списку?

Или перевернуть это: я должен хранить Aи Bв отдельных контейнерах?

1

Решение

Не обращая внимания на специфику различных языков на минуту, и сосредоточив внимание на основной проблеме здесь.

Общая практика

Всякий раз, когда вы объявляете новую переменную (в блоке или также в качестве параметра метода), вы всегда должны рассмотреть возможность объявления ее статический тип быть самым общим, который соответствует вашим потребностям.
Это помогает сделать код намного чище, так как читатель (который может быть и вами, позже в будущем) будет знать, что вы имели в виду, когда писали код.
Кроме того, эта практика поощряет, не слишком задумываясь, практику низкая связь и высокая когезия поскольку он поощряет класс «пользователь» знать как можно меньше о классе «продукт». И, конечно же, это также мотивирует использование интерфейсов, наследование и т. Д.

Ваш пример

Чтобы сделать объяснение более интуитивным, я придаю смысл различным классам.

Давайте предположим, что класс C это «еда». A это «яблоко» и B это «Бургер».

Теперь, если мы хотим иметь коллекцию питание предметы, мы должны создать коллекцию C, Например, перечислить все товары, заказанные в ресторане.
Это позволяет нам использовать функции, известные всем элементам «food», например, «getCalories ()». Итак, когда еда закончится, мы можем повторить эту коллекцию C (Продукты питания), и просто вызывать (и совокупность) some_c_object.getCalories(),

С другой стороны, если мы хотим использовать определенный атрибут (или поведение) A itmes (яблоки), мы бы хотели использовать коллекцию яблок. Например, предположим, что класс реализует метод hasWorms(), Это позволяет нам убедиться, что нет яблоко в нашей коллекции есть червь. Это явно не имеет значения для бургеры ( с надеждой 😉 ).

Как это мотивирует лучшую практику?

Чтобы соединить обе мои предыдущие точки: представьте себе, что вы хотите повторить все ваши заказы, это общая коллекция Food, Но, потому что вы знаете, что Apple в нем могут быть черви, вы хотите убедиться, что те, кто в заказе, не имеют их. У вас может возникнуть соблазн просто повторить корзину, спросите if current_item is Apple и если это так, бросьте это current_item для Apple и проверить HasWorms(), Если есть, отмените заказ.

Но это может (и в большинстве случаев должно) заставить вас подумать немного сложнее. Может быть, вы должны убедиться, что с каждым предметом все в порядке? Например, что цвет мяса бургера является регулярным. Теперь вы можете рассмотреть несколько подходов к этому, но я буду использовать классы, которые у нас уже есть, для простоты (без добавления какого-либо нового интерфейса или чего-то подобного). Можете добавить isValid() метод для Food класс (это может быть абстрактный, например). Apple класс просто вернется HasWorms() и Burger класс вернется True если цвет находится в правильном диапазоне. Затем, когда заказ будет выполнен, вы можете просто позвонить isValid() каждого Food вещь.

Заключение

Это очень простой пример, основанный на том, который вы указали в своем вопросе. Я надеюсь, что это поможет решить вашу дилемму, и я настоятельно рекомендую вам прочитать больше о лучших практиках ООП полиморфизма в Интернете. Есть много замечательных источников, таких как этот.

1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]