2015-08-19 4 views
1

Вот небольшой искусственный пример того, чего я пытаюсь достичь. У меня есть класс со многими параметрами - Dog. У меня есть дочерний класс JumpyDog, и я хочу узнать, как я могу «расширить» экземпляр Dog, чтобы сделать его экземпляром JumpyDog.Java - могу ли я расширить экземпляр класса, чтобы сделать его экземпляром родительского класса?

class Dog { 
    int age, numberOfTeeth, grumpiness, manyOtherParameters; 
    JumpyDog learnToJump(int height) { 
     JumpyDog jumpy = new JumpyDog(this); // I do not want to copy all parameters 
     jumpy.jumpHeight=height; 
     return jumpy; 
    } 
} 

class JumpyDog extends Dog { 
    int jumpHeight; 
    void jump(){} 
} 

Или я могу сказать что-то вроде этого:

Dog dog=new Dog(); 
dog.makeJumpy(); 
dog.jump() 
+0

Вы хотите, чтобы собака была экземпляром JumpyDog, в то время как JumpyDog является экземпляром Dog? – CPerkins

+0

Вы хотите изменить тип объекта после его инициализации. Это невозможно в Java. Вам придется скопировать свойства «Собака» в новый экземпляр «JumpyDog». – dotvav

+0

no, вы не можете магически переключить класс экземпляра после его создания. –

ответ

2

Вы можете реализовать Decorator pattern в Java, чтобы избежать копирования всех полей из исходного объекта во время вашего «расширение», просто внутренне сохраняя ссылку на него, но это не будет Dog больше (потому что Dog класс имеет поля, которые мы не копируем).

class JumpyDog { 
    Dog meAsDog; 
    int jumpHeight; 

    public JumpyDog(Dog me) { 
     meAsDog = me; 
    } 

    public Dog meAsDog() { 
     return meAsDog(); 
    } 

    void jump(){} 
} 

Вы можете использовать его как следующее:

Dog dog=new Dog(); 
JumpyDog meAsJumpy = dog.learnToJump(100); 
meAsJumpy.jump() 

И нет, вы не можете сделать следующее из вашего примера, потому что Dog не имеет jump() метод:

Dog dog=new Dog(); 
dog.makeJumpy(); 
dog.jump() // Dog has no method jump 
+1

Если вы хотите сделать это гораздо более динамичным, вы можете использовать шаблон «Ролевые объекты», который является более крупным шаблоном с использованием шаблона декоратора. Проблема с этим простым подходом заключается в том, что у вас будет объектная шизофрения. – lschuetze

0

вы можете сделать что-то вроде этого:

class Dog { 

    int age; 
    int numberOfTeeth; 
    int grumpiness; 
    int manyOtherParameters; 

    boolean hasLearnedHowToJump; 
    int jumpHeight; 

    void learnToJump(int heigth) { 
     hasLearnedHowToJump = true; 
     jumpHeight = heigth; 
    } 

    void jump(){ 
     if(!hasLearnedHowToJump) { 
      throw new RuntimeException("must learn how to jump first..."); 
     } 
    } 

} 

, то вы можете использовать его так:

Dog dog=new Dog(); 
//dog.jump() would end in a exception... 
dog.learnToJump(100); 
dog.jump() 
0

После dog был объявлен типа Dog это его тип навсегда. Вы можете бросить его на любой суперкласс, но он все равно будет Dog.

Вы можете использовать конструктор копирования. Это на самом деле требует от вас написать код , копирующий код для всех атрибутов, но предложит вам что-то близкое к вашему желаемому стилю.

public class Dog { 

    int age, numberOfTeeth, grumpiness, manyOtherParameters; 

    public Dog() { 

    } 

    public Dog(Dog other) { 
     other.age = this.age; 
     other.numberOfTeeth = this.numberOfTeeth; 
     other.grumpiness = this.grumpiness; 
     other.manyOtherParameters = this.manyOtherParameters; 
    } 
} 


class JumpyDog extends Dog { 

    int jumpHeight; 
    void jump(){} 

    public JumpyDog(Dog other) { 
     super(other); 
    } 

} 

Позволит вам написать что-то вроде:

Dog dog = new Dog(); 
JumpyDog jumpyDog = new JumpyDog(dog); 
jumpyDog.jump(); 

Оставляю тебя с 2-мя экземплярами. Это сделает jumpyDog прыжок, но ничего не сделает на примере dog.

0

Вы можете сделать что-то вроде этого

class Dog { 
    protected int age, numberOfTeeth, grumpiness, manyOtherParameters; 

    protected Dog(Dog g) { 
     // assign all attributes here 
    } 

    JumpyDog learnToJump(int heigth) { 
     return new JumpyDog(this, heigth);; 
    } 


} 

class JumpyDog extends Dog { 

    int jumpHeight; 

    public JumpyDog(Dog dog, int jumpHeight) { 
     super(dog); 
     this.jumpHeight = jumpHeight; 
    } 
    void jump(){} 
} 

Затем вы можете сделать некоторые, как это:

Dog dog=new Dog(); 
JumpyDog jDog = dog.learnToJump(100); 
jdog.jump() 
+0

Это копирование в «назначить все атрибуты здесь», автор хочет избежать этого. –

+0

Этот конструктор может быть сгенерирован всеми IDE, так как атрибуты находятся в одном классе (Dog). – clapsus

0

Лучше всего было бы реализовать Role Object Pattern описываемую связанной бумаги. Это украшение, подобное рисунку, уже предложенному @Philip Voronov. Существует концепция как интерфейс, реализованный ядром и абстрактным классом, представляющим суперкласс всех ролей, которые могут быть воспроизведены объектом. Чтобы уменьшить object schizophrenia (который появляется, когда объекты логической единицы разделены между многими физическими объектами), каждый вызов объекта роли (который не свойственен роли) перенаправляется на основной объект.

Логически ядро ​​и его роли создают единое целое. Но объект разделяется на ядро ​​(которое управляет ролями) и все роли, которые могут быть воспроизведены объектом.

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

Я написал a short implementation, используя ваш сценарий для собак.

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

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

  • Нет связанных вопросов^_^