Решение проблем апскейтинга / спада - PullRequest
1 голос
/ 27 декабря 2011

Есть ли у кого-нибудь подходящая стратегия для решения вопросов кастинга / апкастинга?Я понимаю, когда разрешено использовать апкастинг и апскейтинг, но когда вопросы имеют тенденцию включать несколько объектов, я довольно быстро путаюсь.Например, как лучше всего найти ответ на такой вопрос:

Вопрос: Каков будет результат компиляции следующей программы:

interface Inter{}
class Base implements Inter{}
class Derived extends Base{}

class ZiggyTest2{

    public static void main(String[] args){

        Base b = new Base();
        Derived d = new Derived();
        Inter i = (Base)b;
        i = (Base)d;
        Derived bd = (Derived)b;
        b = (Base)i;        
    }   
}

Меня не очень интересует ответ, а скорее подход к решению вопроса.Есть ли какой-либо подход / стратегия, которую я могу использовать для решения вопроса о повышении или понижении, как описано выше?Например, ссылки / объекты могут быть нарисованы на бумаге, чтобы я мог получить визуальное представление, и это может помочь?

Спасибо

Ответы [ 4 ]

3 голосов
/ 27 декабря 2011

Вот отличная статья о повышении и понижении.

Цитата из статьи -

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

Просто задайте себе вопрос "каков тип объекта?" а затем помните, что разрешено приводить его к любому классу предшественника в классе heirarchy (включая интерфейсы).

В вашем случае вы создаете 2 объекта: Base и Derived. Base можно обозначить Inter или Base, а Derived можно обозначить Inter, Base или Derived. Итак, ваш код будет хорошо скомпилирован. Но во время выполнения, когда вы попытаетесь привести Base b к Derived bd, вы получите ClassCastException.

2 голосов
/ 27 декабря 2011

Есть несколько простых правил

  • Вы можете привести к классу предшественника (вплоть до Object) (никогда не будет)
  • Вы можете привести к подклассу - это может дать сбой во время выполнения
  • Вы можете привести к интерфейсу из класса, который его реализует (никогда не завершается)
  • Вы можете привести из интерфейса к классу iplemneting - это может не сработать во время выполнения

Первые два правила применяются также к интерфейсам.

Вы можете нарисовать диаграмму классов UML , чтобы визуализировать ее (только с реализацией = реализует, расширяет связи), навигация по графику будет безопасной в направлении стрелок. Навигация по другому пути была бы полезной во время выполнения. И навигация без отношения «расширяет / реализует» была бы невозможна.

1 голос
/ 27 декабря 2011

Для меня я хотел бы сначала нарисовать иерархию этих типов.На ваш вопрос «уровни» типов:


Inter (выше)

Base (выше)

Derived


«Уровень» объекта определяется при его создании, и объект может только «подниматься», а не опускаться в зависимости от уровня его создания.Например, объект b создается как объект Base, поэтому он находится на уровне Base.Вы можете легко обнаружить, что b может повышаться до Inter, но не понижаться до Derived, независимо от того, какой тип используется для описания b.Если для описания b используется Inter, поскольку уровень его создания равен Base, вы можете уменьшить его до Base.

1 голос
/ 27 декабря 2011

Если эксплуатируемые объекты находятся в одной и той же иерархии, приведение скомпилируется наверняка, но во время выполнения может произойти сбой.

Например:

class Animal { }
class Dog extends Animal { }
class Bulldog extends Dog { }

Если вы напишите:

Animal animal = new Animal();
Dog d = (Dog) animal;

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

Animal animal = new Animal();
Dog d = (Dog) animal;
String s = (String) animal;

Это, безусловно, завершится ошибкой, поскольку компилятор знает, что String и Dog не находятся в одной иерархии.

Те же правила применяются и к интерфейсам.

Надеюсь, это поможет.

...