2014-09-16 2 views
1

Мне интересно, что конкретно позволяет объекту одного класса быть отличным в качестве другого класса. Глядя на Class.isInstance (Object obj) javadoc, он предполагает, что объект должен быть «совместим с назначением» с другим классом, чтобы быть отличным для этого класса. Но что означает «совместимость с назначением»?Что делает назначение объекта совместимым с другим классом?

Я пытаюсь выяснить, как следующие возвратил ClassCastException:

public class A 
{ 
    multiple private attributes 
    No constructor 
    multiple public methods 
} 

public class B extends A 
{ 
    blank default constructor 
    2 additional private attributes 
    4 additional public getter/setter methods for these attributes 
} 

Линия

B b = (B)variable.getA() // where getA() returned an instance of class A 

возвращает ClassCastException А не может быть брошена как B. Я знаю, что Отливки из родительский класс к подклассу - плохая идея. Я не писал код, о котором идет речь, я просто смотрю на него в качестве поддержки производства.

Класс B является единственным классом в коде, который простирается от А. Таким образом, результат Гета() не является объектом другого подкласса А (скажем, С) приведение к А.

Так почему в этом экземпляр может Java не бросать объект класса A в, казалось бы, совместимый класс B?

+2

_leads Java для believe_ Java не нужно угадать. Он знает, что такое тип объекта. Если это экземпляр конкретного типа 'A', то это не' B'. –

+0

Спасибо Sotirios. Я переформулировал последнее предложение, надеюсь, подытожим немного лучше. И A, и B имеют одинаковые атрибуты и методы, причем B имеет пару дополнительных. Поэтому вы могли бы подумать, что объект класса B может быть создан с использованием атрибутов объекта класса A со значениями по умолчанию класса B, используемыми для дополнительных атрибутов. Этот вопрос направлен на то, чтобы помочь мне понять, почему они кажутся совместимыми, но на самом деле это не так. – lgrayden

+0

Каково ваше определение совместимости. A и B выглядят одинаково в виде A, но B имеет что-то дополнительное. Экземпляр A не может работать как B, потому что у этого экземпляра нет «лишнего», которое имеет только B. Другими словами, B можно отличить как A, потому что «B расширяет A», как вы указали в своем коде. –

ответ

0

Javadoc для Class.isInstance(Object obj) дает определение assignment compatible:

В частности, если этот объект класса представляет собой объявленный класс, этот метод возвращает истину, если указанный аргумент Объект является экземпляром представленного класса (или любого из его подклассов); он возвращает false в противном случае. Если этот объект класса представляет класс массива, этот метод возвращает значение true, если указанный аргумент объекта может быть преобразован в объект класса массива путем преобразования идентичности или с помощью расширенного эталонного преобразования; он возвращает false в противном случае. Если этот объект класса представляет собой интерфейс, этот метод возвращает true, если класс или любой суперкласс указанного аргумента объекта реализует этот интерфейс; он возвращает false в противном случае. Если этот объект класса представляет примитивный тип, этот метод возвращает false.

В принципе, вы можете присвоить объект типа A в переменной типа B, если тип А расширяет или реализует тип B.

+0

Спасибо Рикардо. Это тот ответ, который я искал. Кажется странным, хотя этот код a) Компилирует b), кажется, работает нормально в 99% случаев. Поэтому я подумал, что это может быть нечто более сложное, как сопоставление методов и атрибутов и т. Д. – lgrayden

0

Брошено, чтобы указать, что код попытался передать объект в подкласс, экземпляром которого он не является. Например, следующий код генерирует ClassCastException:

Object x = new Integer(0); 
System.out.println((String)x); 

подробнее here и here.

+0

Эта доза не касается основного вопроса «Что делает объект« совместимым с назначением »с другим классом», и этот пример не имеет значения, так как оба класса похожи, а не состоят из разных типов, таких как Integer/String. – lgrayden

2

Рассмотрим эти два случая:

A a = new B(); 
B b = (B)a; <-- Ok. 

A a = new A(); 
B b = (B)a; <-- ClassCastException 

Поэтому для того, чтобы привести объект к B он должен быть экземпляром B (или подкласс B).

В вашем случае это, однако, является экземпляр А.

0

Если мы заменили А и В с осмысленными именами, которые помогают нам думать о проблеме, то ответ становится яснее. Если А становится Млекопитающим, а В - Собакой, тогда мы можем разумно сказать, что все Собаки - Млекопитающие, но мы не можем сказать, что все Млекопитающие - Собаки. Даже если они поверхностно разделяют одни и те же атрибуты, нет никакой гарантии, что все млекопитающие будут выполнять контракт о Собаке, и компилятор не должен этого делать.

+0

Но разве компилятор не допускает этого, потому что существует вероятность того, что Mammal _might_ сможет выполнить контракт о Собаке? И в моем случае это очень вероятно. – lgrayden

+0

Нет, потому что «возможно», недостаточно. – Romski

Смежные вопросы