Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java中的OOP:带方法链的类继承_Java_Oop - Fatal编程技术网

Java中的OOP:带方法链的类继承

Java中的OOP:带方法链的类继承,java,oop,Java,Oop,我有一个父类,它定义了链表方法(返回“this”的方法)的集合。我想定义多个子类,这些子类包含它们自己的链表方法,但也“覆盖”父类方法,以便返回子类的实例而不是父类 我不想在每个子类中重复相同的方法,这就是为什么我有一个包含所有子类共享的方法的父类。谢谢 class Chain { public Chain foo(String s){ ... return this; } } class ChainChild extends Chain { //I don't w

我有一个父类,它定义了链表方法(返回“this”的方法)的集合。我想定义多个子类,这些子类包含它们自己的链表方法,但也“覆盖”父类方法,以便返回子类的实例而不是父类

我不想在每个子类中重复相同的方法,这就是为什么我有一个包含所有子类共享的方法的父类。谢谢

class Chain {
  public Chain foo(String s){
    ...
    return this;
  }
}

class ChainChild extends Chain {
  //I don't want to add a "foo" method to each child class
  /*
  public ChildChain foo(String s){
    ...
    return this;
  }
  */

  public ChainChild bar(boolean b){
    ...
    return this;
  }
}

ChainChild child = new ChainChild();
child.foo().bar(); //compile error: foo() returns a "Chain" object which does not define the bar() method. 

父类中返回
this
的方法仍将返回对子类对象的引用。您只能将其视为父类的对象(除非强制转换),但它实际上是其原始类型

你可以考虑使用这样的泛型:

// This seems a bit too contrived for my liking. Perhaps someone else will have a better idea.
public class Parent<T extends Parent<T>> {
    T foo () {
        return (T) this;
    }
}

public class Child extends Parent<Child> {
    public void bar () {
        Child c = foo();
    }
}
//这对我来说似乎有点太做作了。也许其他人会有更好的主意。
公共类父类{
T foo(){
返回(T)这个;
}
}
公共类子级扩展父级{
公共空白栏(){
Child c=foo();
}
}
你可以直接施放它

ChainChild child = new ChainChild();
((ChainChild) child.foo()).bar();
你可以试试:

public ? extends Chain foo() {
    return this;
}

但我不确定这是否有帮助,即使它可以编译。

我已经根据您的需要使用泛型编写了这个示例

class Parent {
    public <T extends Parent> T foo() {
        return (T)this;
    }
}

class Child extends Parent {

}

class AnotherChild extends Parent {

}

public class Test {
    public static void main(String[] args) {

        Parent p = new Child();
        System.out.println(p);
        Child c = p.foo();
        System.out.println(c);
        //throws ClassCastException here since Child is not AnotherChild
        AnotherChild ac = p.foo();
        System.out.println(ac);
    }
}
类父类{
公共图书馆{
返回(T)这个;
}
}
类子级扩展父级{
}
类的另一个子类扩展父类{
}
公开课考试{
公共静态void main(字符串[]args){
父p=新的子();
系统输出println(p);
Child c=p.foo();
系统输出打印ln(c);
//在此处抛出ClassCastException,因为孩子不是另一个孩子
另一个孩子ac=p.foo();
系统输出打印项次(ac);
}
}

以下是对OldCurmudgeon方法的改进:

public class Parent<This extends Parent<This>> {

    @SuppressWarnings("unchecked")
    private final This THIS = (This)this;

    public This foo() {
        //...
        return THIS;
    }

    public This bar() {
        //...
        return THIS;
    }    
}

public class Child extends Parent<Child> {

    // you can override super with covariant return type
    @Override
    public Child bar() {
        super.bar();

        return this;
    }
}


Child child = 
new Child()
.foo()
.bar();
公共类父类{
@抑制警告(“未选中”)
私人决赛This=(This)This;
公开此foo(){
//...
归还这个;
}
公共酒吧(){
//...
归还这个;
}    
}
公共类子级扩展父级{
//您可以使用协变返回类型覆盖super
@凌驾
公共儿童酒吧(){
super.bar();
归还这个;
}
}
儿童=
新生儿()
.foo()
.bar();
改进是只进行一次未检查的强制转换,并将其保存为常量THIS,您可以将其作为方法链接的返回值重用

这将删除每个方法中未检查的强制类型转换,并使代码更清晰


您可以通过返回子对象而不是此(协变返回类型)来重写父对象的方法

我意识到这一点。但问题是,即使它是同一个对象,我也不能调用子类中的方法,因为该对象被类型转换为父类。我认为@luiggi的技术可能会更整洁。我很好奇,您在什么情况下使用这种(
child.foo().bar();
)调用?@vijay所有子类都使用某些设置。例如,有一个方法使用布尔参数来启用/禁用某个设置。@vijay如果您感到好奇,可以在这里找到该类:我已经找到了某个解决方案,但不知道是否有更好的方法来实现它。:)@迈克尔:谢谢你分享回购协议。我不想强制转换:)这个
?extends
可能会起作用,但我不确定-本质上,您是在尝试假定作为封装基础的一部分对您隐藏的信息,虽然从技术上讲,它只是在转换发生的地方移动。@PhilipWhitehouse这就是OP所寻找的。这里的问题是T是从变量声明推断出来的,而不是从类本身推断出来的。