2014-02-05 2 views
0

Возможно ли использовать родительский объект для создания экземпляра дочернего объекта? Класс Length2 расширяет Length1 с добавлением переменной экземпляра. Common Я попытался создать конструктор копирования, который принимает Length1 как параметр и устанавливает дополнительный ivar равным 0, но мне все еще говорят, что я не могу преобразовать из Legnth1 в Length2. Я полагаю, что может произойти какое-то неявное литье ... взгляните.Написание Java-конструктора для дочернего класса, который принимает родительский объект

public class Length1 extends Length implements Comparable<Length1>{ 

    protected int miles; 
    protected int yards; 

    public Length1(){ //default constructor 
     miles = 0; 
     yards = 0; 
    } 

    public Length1(int m, int y){ //constructor 
     miles = m; 
     yards = y; 
    } 

    public void setYards(int x){ 
     yards = x; 
    } 
    public void setMiles(int x){ 
     miles = x; 
    } 
    public int getYards(){ 
     return yards; 
    } 
    public int getMiles(){ 
     return miles; 
    } 

...

public class Length2 extends Length1 { 

    protected int feet; 

    public Length2(){ //default constructor 
     super(0,0); 
     setFeet(0); 
    } 
    public Length2(int m, int y, int f){ // constructor 
     super(m,y); 
     setFeet(f); 
    } 
    public Length2(Length1 x){ 
     super(x.miles,x.yards); 
     setFeet(0); 
    } 
    public void setFeet(int x){ 
     feet = x; 
    } 
    public int getFeet(){ 
     return feet; 
    } 

...

public class LengthTest{ 

    public static void main(String[] args) { 
     Length1 a,b,c,d,e,f; 
     Length2 g,h,i,j; 

     a = new Length1(78,1610); 
     b = new Length1(77,1694); 
     c = new Length1(); 
     d = new Length1(); 

     g = new Length2(32,1022,1); 
     h = new Length2(31,1700,2); 
     i = new Length2(); 
     j = new Length2(); 


     j = c; //problem occurs here 


    } 

} 
+0

ну, вот как наследование работает. если L2 более специфичен, чем L1, вы не можете сказать, что некоторые L2 = L1, потому что L2 должен знать некоторую информацию о полях, которые являются специфическими для L2, которые не присутствуют в L1. – Leo

+1

, конечно, вы можете создать некоторый L2, а затем сказать, что это L1, а затем попытаться сказать, что это L2 снова. Для этого вам нужно пересечь пальцы и выполнить операцию литья. – Leo

+0

. Есть ли рабочая среда, где я мог бы написать метод для создания объекта? Мне нужны только два ивара, содержащиеся в объекте L1, для копирования на объект L2. Да, я знаю, что это практически не имеет смысла:/ – Ktmock13

ответ

0

Как Лео сказал, что если L1 является супер тип L2, что означает L2 имеет все L1, а затем некоторые , Поэтому, если вы попытаетесь создать L2 из L1, информация будет отсутствовать.

+0

Вы бы также рекомендовали метод литья, который заполнил бы отсутствующую информацию при назначении L2 = L1? – Ktmock13

+1

@ Ktmock13 - нет такого волшебного метода кастинга. Лучший способ сделать это - написать код для копирования полей ... вручную. –

+0

Вы создали 'Length1', когда вы сказали' c = new Length1() '. Этот объект всегда будет 'Length1', навсегда, пока он не будет уничтожен. Поэтому, если вы хотите объект 'Length2', вам нужно создать новый объект. – ajb

0

Мой ответ: нет, вы не можете к сожалению. Но вы можете попытаться вытолкнуть всю полезную информацию из L1 в L2, используя какой-то метод L2 = L2.valueOf (L1), который копирует все известные поля из L1 в L2, оставляя пустые. Вы должны написать этот метод вручную. Возможно, вы можете сэкономить время на повторное использование некоторого L1-конструктора в L2.

0

Вы не можете этого сделать. Length2 IS A Length1, поэтому вы всегда можете назначить Length2объекту на ссылку Length1 (вам никогда не придется бросать ее). Вы также можете назначить ссылку Length1, которая указывает на объект Length2 на другую ссылку, объявленную как Length2. В этом случае вам нужен явный приведение, потому что компилятор во время компиляции не знает, что ссылка Length1 на самом деле является Length2. Но то, что вы пытаетесь сделать, невозможно, так как Length1 НЕ А Length2.

Это как сказать, что Car extends Vehicle. Вы всегда можете указать на Car и сказать Car.

Car c = new Car(); 

Это всегда нормально. И вы всегда можете указать на один и сказать Vehicle:

Vehicle v = new Car(); 

Нет проблем. Единственная проблема, с которой вы столкнетесь, заключается в том, что вы решили вызвать, например, метод printLicensePlate()Car, которого нет в Транспортном средстве, который имеет мелход под названием printSpeed(). Поскольку Car ЯВЛЯЕТСЯ `Автомобиль, вы всегда можете позвонить:

c.printSpeed(); 
c.printLicensePlate(); 

и

v.printSpeed(); 

Но вы не можете позвонить:

v.printLicensePlate(); 

даже если вы знаете, что v является Car. Это тот случай, когда вы используете трансляцию, чтобы преобразовать ссылку.Это незаконно:

c = v; // WRONG 

, потому что в время компиляции мы не знаем, что на самом деле в c, так как new Car() происходит только при выполнения. Так компилятору «поверьте мне, это действительно Car», выполнив:

c = (Car) v; 

Но что вы сделали что-то вроде:

Car c = new Vehicle(); // WRONG 

Вы указали на родовом Vehicle и сказал Car. В то время как Car всегда Vehicle, Vehicle может не быть автомобилем. (Используя ссылку c, компилятор считает, что вы можете на законных основаниях называть c.printLicensePlate(), но во время выполнения объект, который вы обнаружите, не имеет такого метода. Поэтому, даже если вы можете передать это компилятором путем литья ссылки, это не сработает и будет производить a ClassCastException во время выполнения.)

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