Запутаться в ссылочном приведении и расширении объектов w.r.t в Java - PullRequest
2 голосов
/ 23 января 2010

С примитивами и их оболочками я понял концепцию расширения. Но в отношении других Объектов я путаюсь с Расширением и неявным Кастингом. Как пример

       Class Animal{
        }

        Class Dog extends Animal{

         public static void main(args String[]){

         Dog d = new Dog();
         d.go(d);
        }

       void go(Animal a){    }
      }

Редактировать: вопрос в том, какой из них предпочтительнее для расширения или кастинга и почему?

Ответы [ 2 ]

1 голос
/ 23 января 2010

(по моему мнению), если кастинг не требуется, не делайте этого. Ваш код будет более читабельным.

В частности, синтаксис:

 d.go(d);

более кратко и точно так же, как

d.go((Animal)d);

По сути, воспользуйтесь преимуществами расширения по причинам, которые я опишу ниже, в моей первой попытке ответить на ваш вопрос.


Ну, это зависит от того, что вы хотите, чтобы код выполнял.

Если вам нужна функция, которая может работать с любыми животными, собаками или иным образом, то вы должны взять в качестве входных данных животное.

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

edit: возможно, более надуманный пример проиллюстрирует, почему это не вопрос с простым и универсальным ответом. В Java все объекты являются дочерними для Object, и поэтому любой метод может быть написан так, что он принимает параметр Object foo.

Иногда это может быть полезно, но его варианты использования довольно ограничены, вы ограничены определенными методами в Object.

Предположим, вместо этого вы знаете о Dog, который также является Object. Вместо того, чтобы передавать экземпляр Dog как Object, вы можете захотеть получить свойство определенное до Dog. По сути, если вам нужно убедиться, что аргумент какой-либо функции соответствует какому-либо контракту, вы должны ограничить аргумент типами, которые соответствуют - немного по-другому: , если вам нужно знать, что это Dog, объявите его как Dog . * * 1033

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

0 голосов
/ 23 января 2010

Я согласен с Марком в том, что это зависит. Я использую эмпирическое правило, которое в основном просто говорит, что приведение объявленных типов к подтипу «плохо». Так что если где-то в вашем методе

void go(Animal a){ ... }

вам нужен актерский состав как

Dog d = (Dog) a;

Вы должны обязательно (если возможно) изменить параметр a типа Animal на параметр типа Dog. Если метод работает на всех подтипах Animal без приведения, оставьте его как есть.

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