Считается ли проверка типов плохой практикой, даже если вы проверяете интерфейс? Я понимаю, что вы всегда должны программировать интерфейс, а не реализацию - это то, что это значит?
Например, в PHP это нормально?
if ($class instanceof AnInterface) {
// Do some code
}
Или есть лучший способ изменить поведение кода на основе типа класса?
Редактировать: Для ясности я говорю о проверке того, является ли класс орудия интерфейсом, а не просто экземпляром определенного класса.


Если вы можете избежать проверки типов, вам следует; однако один сценарий, в котором я нашел это удобным, заключался в том, что у нас была веб-служба, принимающая сообщение, но содержимое сообщения могло измениться. Нам пришлось сохранить сообщение обратно в базу данных, чтобы получить правильный компонент, чтобы разбить сообщение на соответствующие таблицы, мы в некотором смысле использовали проверку типов.
То, что я считаю более распространенным и гибким, чем if ($ class instanceof SomeOtherType), - это, например, определение стратегии IProcessing, а затем использование factory на основе типа $ class для создания правильного класса.
Итак, в C# примерно это:
void Process(Message msg)
{
IProcessor processor=ProcessignFactory.GetProcessor(msg.GetType());
processor.Process(msg);
}
Однако иногда это может быть излишним, если вы имеете дело только с одним вариантом, который не изменится, реализуйте его с помощью проверки типа, и когда / если вы обнаружите, что были неправы, и это требует дополнительных проверок, затем реорганизуйте его в более надежное решение.
Пока вы следуете LSP, я не вижу проблемы. Ваш код должен работать с реализацией интерфейса любой. Не проблема, что определенные реализации заставляют вас следовать различным путям кода, если вы можете правильно работать с реализацией интерфейса любой.
Если ваш код не работает со всеми реализациями интерфейса, вам не следует использовать интерфейс в первую очередь.
Конечно, пока подкласс реализует интерфейс, никаких изменений вносить не нужно?
В моей практике любая проверка типа (а также приведение типов) всегда указывала на то, что что-то не так с кодом или языком.
Поэтому я стараюсь по возможности избегать этого.
Как эффективно определять количество элементов в бесчисленной коллекции без приведения типов?
Проверка типов во время выполнения часто необходима в ситуациях, когда интерфейс предоставляет все методы, необходимые для того, чтобы что-то делать, но не предоставляет достаточно, чтобы делать это хорошо. Ярким примером такой ситуации является определение количества элементов в перечислимой последовательности. Такое определение можно сделать путем перечисления в последовательности, но многие перечислимые объекты «знают», сколько элементов они содержат. Если объект знает, сколько элементов он содержит, вероятно, будет более эффективным запросить его, чем перечислять через коллекцию и подсчитывать элементы по отдельности.
Возможно, IEnumerable должен был предоставить некоторые методы, чтобы спросить, что ему известно о количестве элементов, которые он содержит [признавая возможность того, что объект может знать, что это число неограниченно или что оно не превышает 4591 (но может быть намного меньше), и т. д.], но это не так. Идеальным было бы создание новой версии интерфейса IEnumerable, которая включала бы реализации по умолчанию для любых «новых» методов, которые он добавляет, и если бы такой интерфейс можно было считать реализованным любыми реализациями текущей версии. К сожалению, поскольку такой функции не существует, единственный способ получить счетчик перечисляемой коллекции без ее перечисления - это проверить, реализует ли она какие-либо известные интерфейсы коллекции, которые включают член Count.
Это просто проблема с методами расширения C#, поскольку они разрешаются статически и не являются полиморфными. Если бы C# поддерживал черты, классы могли бы специализироваться на реализации Count, если бы они могли обеспечить более эффективную реализацию.
@Lee: Правильный подход, IMHO, состоял бы в том, чтобы иметь код в загрузчике классов .NET, который мог бы обрабатывать методы интерфейса, для которых не существует реализации, указав vtable на статическую реализацию, связанную с интерфейсом [одна версия для структур и один для классов], сигнатура которого включала в качестве первого параметра ссылку или byref на тип реализации. Это добавило бы немного времени к процессу загрузки класса, но позволило бы интерфейсам, таким как IList<T>, включать методы, которые были бы полезны с некоторыми, но не всеми реализациями, без принуждения ...
... все реализации IList<T> включают стандартные заглушки для неиспользуемых методов.
Это хороший момент, но легко поставить себя в ситуацию, когда вам придется обновлять метод каждый раз, когда добавляется новый подкласс, если вы выполняете проверку типов. Этого следует избегать в пользу полиморфизма.