Привести интерфейс к его конкретному объекту реализации или наоборот? - PullRequest
36 голосов
/ 12 февраля 2009

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

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

Ответы [ 5 ]

44 голосов
/ 12 февраля 2009

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

То есть, если у вас есть 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 вокруг явных приведений. В C # у вас есть полезное ключевое слово as:

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

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

14 голосов
/ 12 февраля 2009

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

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

3 голосов
/ 12 февраля 2009

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

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

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

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

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

0 голосов
/ 29 декабря 2016

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

0 голосов
/ 12 февраля 2009

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...