В С#, когда у меня есть интерфейс и несколько конкретных реализаций, могу ли я применить интерфейс к конкретному типу или конкретный тип, передаваемый в интерфейс?
Каковы правила в этом случае?
В С#, когда у меня есть интерфейс и несколько конкретных реализаций, могу ли я применить интерфейс к конкретному типу или конкретный тип, передаваемый в интерфейс?
Каковы правила в этом случае?
Оба направления разрешены в 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
".)
В большинстве языков вы можете использовать оба направления. Если у вас есть конкретный класс, вы можете применить его к интерфейсу. Если у вас есть интерфейс, его можно применить к конкретному классу.
Как правило, вы хотите идти только в первом направлении. Причина в том, что вы не должны знать, что такое конкретный класс, когда у вас есть только указатель на интерфейс. Если вы передаете что-то в качестве интерфейса, вы должны иметь возможность делать все, что вам нужно, от этого интерфейса. Если вам нужно использовать части конкретного объекта, а не интерфейс, у вас есть проблема с дизайном, которая должна быть исправлена, а не кастинг.
Если вы говорите о Java (но правила для других языков похожи), это примерно так:
Вы можете (вниз) применить интерфейс к конкретной реализации, если ссылка, которую вы нарисовали, фактически является ссылкой на конкретную конкретную реализацию. Это означает
Vehicle v=new Car();
(Car)v // this is OK
(Bus)v // this is not
Ошибка проявляется как ClassCastException
в Java.
Вы можете полностью реализовать конкретную реализацию интерфейса для интерфейса.
Оба действительны, считая его логическим. Много раз пользователи вашего интерфейса не имеют доступа к конкретным классам, что является одной из основных причин наличия интерфейса в первую очередь.
Интерфейс может быть целым классом, если не должен быть, лучше, когда вы создаете конструктор, который принимает интерфейс как параметр и копирует Настройки, таким образом, вы контролируете, что происходит и что нужно.