Способ заставить метод родительского класса Java возвращать объект дочернего класса - PullRequest
28 голосов
/ 27 октября 2010

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

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

Обновление:

Извините, что мне было не так ясно.

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

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

Ответы [ 6 ]

61 голосов
/ 27 октября 2010

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

public class Parent<T> {

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

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

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
7 голосов
/ 27 октября 2010

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

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

3 голосов
/ 27 октября 2010

Просто для демонстрации:

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

     return this.getClass().newInstance();
  }
}
2 голосов
/ 27 октября 2010

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

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

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

return this.getClass().newInstance(); // sometimes works
1 голос
/ 27 октября 2010

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

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

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

0 голосов
/ 27 октября 2010
public class Parent {
    public Parent myMethod(){
        return this;
    }
}
public class Child extends Parent {}

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...