2015-02-16 2 views
0

Я ищу способ иметь в абстрактном методе возвращаемый тип, который будет одним из вариантов реализации, вызывающим метод.Динамический возвращаемый тип реализации, объявленный абстрактным методом

Другими словами, я хотел бы написать что-то вроде этого:

public class GenericClass { 

    public <T extends GenericClass> T returnMyself() { 
    return (T)this; // Compiler warning, unsafe cast 
    } 
} 

public class Implem1 extends GenericClass {} 

public class Implem2 extends GenericClass {} 

public class Main { 

    public static void main(String[] args) { 
    Implem1 implem1 = new Implem1(); 
    Implem1 again1 = implem1.returnMyself(); // Works fine, the type is inferred by the type of again1, I think 
    Implem1 again2 = implem1.<Implem1>returnMyself(); // Works fine, the type is explicitly asked by <Implem1> 
    Implem2 again3 = implem1.returnMyself(); // Works fine while it shouldn't. 
    } 

} 

То, что я ищу является способ объявить метод так, что во время компиляции, returnMyself() может возвращать только тип (в моем примере, implem1 имеет тип Implem1), и убедитесь, что вызов кода не может ошибочно/смешивать типы.

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

Некоторые ответы были правильными, но всегда подразумевались для переопределения метода в каждом классе реализации, который может быть громоздким и подверженным ошибкам на моей стороне. Я идеально ищу метод, который мне пришлось бы писать только один раз в классе Abstract.

Любая помощь/ответ оценил: D

ответ

1

Вы можете сделать это следующим образом:

public class Parent { 
    public Parent returnMyself() { 
     return this; 
    } 
} 

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

Это это не проблема, потому что если вы храните экземпляр Child в переменной Parent, тогда вы ожидаете возврат Parent типа returnMyself(). Даже если это фактически объект Child, Child, возвращенный returnMyself(), расширяет Parent, так что вы идете.

+0

Хотя это делает трюк, для этого требуется переопределить каждый дочерний класс, чтобы написать почти тот же фрагмент кода (кроме типа возврата). Я ожидал, что смогу написать его раз и навсегда в абстрактном классе ... Но я думаю, что это невозможно в Java? – jdebon

+0

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

+0

Принимая ответ, потому что это самый близкий ответ на мой вопрос, хотя я как бы надеялся, что будет более разумный способ :(Спасибо вам! – jdebon

0

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

Can overridden methods differ in return type?

+0

Ну точно, я предпочел бы не писать его снова в каждом дочернем классе: D – jdebon

+0

Вы можете вернуть объект вместо: P Я не уверен, что вы можете делать то, что вы хотите. –

0

Поскольку вы упоминаете абстракцию в описании проблемы, как насчет модели, похожей на класс Enum Java, где общий тип находится в определении класса?

public abstract class GenericClass<T extends GenericClass> { 

    public abstract T returnMyself(); 
} 

public class Implem1 extends GenericClass<Implem1> { 

    @Override 
    public Implem1 returnMyself() { 
     return this; 
    } 
} 

public class Implem2 extends GenericClass<Implem2> { 

    @Override 
    public Implem2 returnMyself() { 
     return this; 
    } 
} 

public class Main { 

    public static void main(String[] args) { 
     Implem1 implem1 = new Implem1(); 
     Implem1 again1 = implem1.returnMyself(); // Works fine 
     Implem1 again2 = implem1.returnMyself(); // Works fine 
     Implem2 again3 = implem1.returnMyself(); // Does not compile 
    } 

}