2010-10-27 3 views
24

Есть ли элегантный способ заставить Java-метод размещаться в родительском классе объекта возврата дочернего класса, когда этот метод вызывается из дочернего класса?Способ вернуть метод родительского класса Java возвращать объект дочернего класса

Я хочу реализовать это, не используя дополнительные интерфейсы и дополнительные методы, и использовать это без применения классов, вспомогательных аргументов и т. Д.

Update:

Извините, что я не так ясно.

Я хочу реализовать цепочку методов, но у меня проблемы с методами родительского класса: я теряю доступ к методам дочерних классов, когда я вызываю методы родительского класса ... Я полагаю, что я представил ядро ​​моего идея.

Таким образом, методы должны возвращать this объект this.getClass() класс.

ответ

46

Если вы просто ищете способ построения цепочки против определенного подкласса, то должно работать:

public class Parent<T> { 

    public T example() { 
    System.out.println(this.getClass().getCanonicalName()); 
    return (T)this; 
    } 
} 

, которые могут быть абстрактными, если вы хотите, то некоторые дочерние объекты, которые определяют общий тип возвращаемого значения (это означает, что вы не можете получить доступ к childBMethod из childâ):

public class ChildA extends Parent<ChildA> { 

    public ChildA childAMethod() { 
    System.out.println(this.getClass().getCanonicalName()); 
    return this; 
    } 
} 

public class ChildB extends Parent<ChildB> { 

    public ChildB childBMethod() { 
    return this; 
    } 
} 

, а затем использовать его как этот

public class Main { 

    public static void main(String[] args) { 
    ChildA childA = new ChildA(); 
    ChildB childB = new ChildB(); 

    childA.example().childAMethod().example(); 
    childB.example().childBMethod().example(); 
    } 
} 

выход будет

org.example.inheritance.ChildA 
org.example.inheritance.ChildA 
org.example.inheritance.ChildA 
org.example.inheritance.ChildB 
org.example.inheritance.ChildB 
+0

Большое вам спасибо. Это то, чего я хочу. –

+0

@Errandir Нет проблем - рад помочь –

+1

отлично. Но мне нужно добавить '@SuppressWarnings (« unchecked »)' to 'example()'. –

1

Я точно знаю, что вы имеете в виду, в Perl есть $class переменные, которая означает, что если вы вызываете какой-либо метод фабрики на подклассе, даже если он не переопределен в подклассе, если он instanciates всех экземпляров $class Экземпляра подкласс будет создан.

Smalltalk, Objective-C, многие другие языки имеют аналогичный объект.

Увы, в Java нет такого эквивалентного средства.

+0

В Perl нет такой вещи, как общий встроенный '$ class' переменной на всех. Он ** может быть вычислен ** путем извлечения первого аргумента методу класса (например, 'MyClass-> mySub()' pass pass 'MyClass '' в качестве первого параметра) или путем принятия 'ref()' из object (который является первым аргументом метода, вызываемого объектом, например '$ myclass_object-> mySub()' call pass '$ myclass_object' как первый параметр и' ref ($ myclass_object) 'возвращает' MyClass '') , Пожалуйста, узнайте, о чем вы говорите. – DVK

+0

Но, как вы говорите, первым аргументом метода класса всегда является имя класса, к которому был применен метод. Это означает, что вы можете писать методы, которые затем выполняют '$ class-> newInstance()', которые будут создавать экземпляры подклассов, если метод вызывается в подклассе. Полезно для заводских методов, шаблона шаблона метода в конструкции и т. Д. В Java статический MyObj newInstance() {..} 'всегда будет генерировать' MyObj', даже если вы вызываете 'MySubObj.newInstance()', и нет никакого способа обойти это, например, например. в Perl. –

3

Просто, чтобы продемонстрировать:

public Animal myMethod(){ 
    if(this isinstanceof Animal){ 
    return new Animal(); 
    } 
    else{ 

    return this.getClass().newInstance(); 
    } 
} 
+0

Этот метод должен быть изменен снова и снова, поскольку подклассы добавляются, изменяются и удаляются. Тем не менее, решение тем не менее. – BoltClock

+0

@BoltClock, просто продемонстрировал, я решил вашу проблему в этом обновлении. –

2

Вы можете позвонить this.getClass(), чтобы получить класс выполнения.

Однако это не обязательно класс, называемый методом (он может быть еще ниже по иерархии).

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

return this.getClass().newInstance(); // sometimes works 
+0

Это звучит так: родитель может произвести ребенка через отражение, но это не гарантирует его. :) –

+0

Это будет подкласс текущего класса, потому что 'this' всегда есть. Однако это может быть косвенный подкласс. – Thilo

0
public class Parent { 
    public Parent myMethod(){ 
     return this; 
    } 
} 
public class Child extends Parent {} 

И вызвать его как

 Parent c = (new Child()).myMethod(); 
     System.out.println(c.getClass()); 

Является ли это решение правильным? Если да, то как он отличается от решения №1?

7

Что вы пытаетесь достичь? Это звучит неплохо. Родительский класс не должен знать ничего о своих дочерних элементах. Кажется, это ужасно близко к разрыву Liskov Substitution Principle. Я чувствую, что ваш вариант использования будет лучше служить, изменив общий дизайн, но трудно сказать без дополнительной информации.

Извините, что звучит немного педантично, но я немного боюсь, когда читаю такой вопрос.

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