Включить интерфейс к конкретному объекту реализации или наоборот?

В С#, когда у меня есть интерфейс и несколько конкретных реализаций, могу ли я применить интерфейс к конкретному типу или конкретный тип, передаваемый в интерфейс?

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

Ответ 1

Оба направления разрешены в Java и С#. Downcasting требует явного приведения и может генерировать исключение, если объект не соответствует правильному типу. Тем не менее, для повышения рейтинга нет явного приведения в действие и всегда безопасно.

То есть, если у вас есть public interface Animal и две реализации этих interface, Cat и Dog....

Animal meowAnimal = new Cat();  // No cast required
Animal barkAnimal = new Dog();  // No cast required

Cat myCat = (Cat) meowAnimal; // Explicit cast needed
Dog myDog = (Dog) barkAnimal; // Explicit cast needed

Dog myPet = (Dog) meowAnimal; // Will compile but throws an Exception

и вам понадобится try/catch вокруг явных бросков. В С# у вас есть полезное ключевое слово as:

Dog myDog = barkAnimal as Dog;
Dog myPet = meowAnimal as Dog;

Никакое исключение не будет выбрано, а myDog будет не нулевым, а myPet будет null. Java не имеет эквивалентного ключевого слова, хотя вы всегда можете использовать тесты if (meowAnimal instanceof Dog), чтобы сохранить безопасность типов. (Я бы предположил, что ключевое слово "as" генерирует байт-код, который выполняет if, присваивая нуль is. Но, возможно,.NET имеет инструкцию байт-кода, которая выполняет эквивалент "as".)

Ответ 2

В большинстве языков вы можете использовать оба направления. Если у вас есть конкретный класс, вы можете применить его к интерфейсу. Если у вас есть интерфейс, его можно применить к конкретному классу.

Как правило, вы хотите идти только в первом направлении. Причина в том, что вы не должны знать, что такое конкретный класс, когда у вас есть только указатель на интерфейс. Если вы передаете что-то в качестве интерфейса, вы должны иметь возможность делать все, что вам нужно, от этого интерфейса. Если вам нужно использовать части конкретного объекта, а не интерфейс, у вас есть проблема с дизайном, которая должна быть исправлена, а не кастинг.

Ответ 3

Если вы говорите о Java (но правила для других языков похожи), это примерно так:

Вы можете (вниз) применить интерфейс к конкретной реализации, если ссылка, которую вы нарисовали, фактически является ссылкой на конкретную конкретную реализацию. Это означает

Vehicle v=new Car();
(Car)v // this is OK
(Bus)v // this is not

Ошибка проявляется как ClassCastException в Java.

Вы можете полностью реализовать конкретную реализацию интерфейса для интерфейса.

Ответ 4

Оба действительны, считая его логическим. Много раз пользователи вашего интерфейса не имеют доступа к конкретным классам, что является одной из основных причин наличия интерфейса в первую очередь.

Ответ 5

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