2010-10-27 355 views
24

当从子类对象调用此方法时,是否有任何优雅的方法可以使Java方法位于子类的父类返回对​​象中?如何让Java父类方法返回子类的对象

我想在不使用其他接口和额外方法的情况下实现此功能,并且不使用类转换,辅助参数等等。

更新:

对不起,我是不太清楚。我想要实现方法链,但我有父类方法的问题:当我调用父类方法时,我失去对子类方法的访问... 我想我已经提出了我的核心理念。

所以方法应该返回this对象this.getClass()类。

回答

46

如果你只是在寻找方法链接对定义的子类,那么下面应该工作:

public class Parent<T> { 

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

如果你喜欢,那么指定通用返回类型的一些子对象可能是抽象的(这意味着你不能从ChildA访问childBMethod):

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

非常感谢。这正是我想要的。 – 2010-10-27 13:16:26

+0

@Errandir没问题 - 很高兴帮助 – 2010-10-27 13:17:22

+1

完美。但是我需要将'@SuppressWarnings(“unchecked”)'添加到'example()'中。 – 2012-10-01 02:52:10

1

我确切地知道你的意思,在Perl中有$class变量,这意味着如果你在子类上调用一些工厂方法,即使它没有在子类中重写,如果它实例化任何$class实例子类将被创建。

Smalltalk,Objective-C,许多其他语言都有类似的功能。

唉,在Java中没有这样的等效工具。

+0

在Perl中,根本不存在通用的内置'$ class'变量。它可以通过检索类方法的第一个参数(例如,MyClass-> mySub()调用作为第一个参数传递MyClass)或者通过获取object(这是调用对象的方法的第一个参数,例如'$ myclass_object-> mySub()'调用将'$ myclass_object'作为第一个参数,'ref($ myclass_object)'返回'“MyClass”') 。请知道你在说什么。 – DVK 2010-10-27 10:08:01

+0

但是,正如你所说,类方法的第一个参数始终是该方法应用于的类的名称。这意味着您可以编写方法,然后执行'$ class-> newInstance()',如果在子类上调用该方法,将会创建子类的实例。用于工厂方法,施工中的模板方法模式等等。在Java中,即使调用MySubObj.newInstance(),静态MyObj newInstance(){..}也将总是生成一个MyObj,并且没有任何方法可以解决这个问题。在Perl中。 – 2010-10-27 12:14:23

3

只需证明:

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

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

随着子类的添加,更改和删除,此方法必须一次又一次地更改。尽管如此,仍然是一个解决方案。 – BoltClock 2010-10-27 09:58:32

+0

@BoltClock,刚刚证明,我已经解决了您在此更新中的问题。 – 2010-10-27 10:02:49

2

您可以拨打this.getClass()获得运行时类。

但是,这不一定是调用该方法的类(它可能会更进一步向下)。

而且您需要使用反射来创建新的实例,这很棘手,因为您不知道子类具有哪种类型的构造函数。

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

听起来像:父母可以通过反思产生一个孩子,但不能保证是他的。 :) – 2010-10-27 10:35:15

+0

它将成为当前类的一个子类,因为“this”总是。不过,它可能是一个间接的子类。 – Thilo 2010-10-28 01:12:19

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

并调用它像

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

这个解决办法是正确的?如果是,那么它与第一种解决方案有什么不同?

7

你想达到什么目的?这听起来像个不好的主意。家长不应该对其子女有任何了解。看起来非常接近打破Liskov Substitution Principle。我的感觉是,通过改变总体设计可以更好地服务您的用例,但是如果没有更多信息,很难说。

抱歉听​​起来有点迂腐,但是当我看到这样的问题时,我有点害怕。