链接子类对象的方法,从两个类返回此方法的方法

时间:2014-07-25 08:24:29

标签: java this subclass

我有2个班级:

public class A {
    private final List<String> list;

    public A() {        
        list = new ArrayList<String>();
    }   

    public A first(String s) {      
        list.add(s);
        return this;
    }   

    public A second() {
        System.out.println(list);
        return this;
    }
}

public class B extends A {
    public B bfisrt() {
        System.out.println("asd");
        return this;
    }
}

和一个带有main的类,主要工作中的以下代码

B b = new B();

b.first("unu")
    .second();   

b.bfirst(); 

但我想在同一个对象上链接两个类的方法。那可能吗?像

B b = new B();

b.first("unu")
    .second()   
    .bfisrt();  

4 个答案:

答案 0 :(得分:4)

让我们分解吧。

public A first(String s){       
    list.add(s);
    return this;
}   

方法的返回类型为A,因此调用new B().first("hi")会返回A类型的对象。因此,当我尝试编译时,我预计会出现错误incompatible types

您可以像标记空间的答案一样覆盖方法并执行相同操作,但返回B

public B first(String s){  
    super.first( s );     
    return this;
}   

甚至

public B first(String s) {  
    return (B)super.first(s);     
}   

Kesheva的方法要求您在返回类型为A时手动投射,但您知道它是B

B b = new B();
((B)b.first("unu").second()).bfisrt();

但是,特别是对于需要多次投射的较长链,这是高度代码混乱的。

这是另一种可能符合您需求的解决方案。

public abstract class A {
    public <Unknown extends A> Unknown first(String s) {
        System.out.println("in here");
        return (Unknown)this;
    }
}

public class B extends A { }

public static void main(String[] args) {
   //compiles without overriding the method or manually casting. 
    B b = new B().first("hi").first("hello");
}

this StackOverflow thread上,您可以阅读 这样做的原因。

编辑:正如newacct指出的那样,它可能有些安全,但如果你不使用构建器模式,那么只能 你不看你分配给什么。考虑下面的两段代码:

B b = new B().first("hi").first("hello"); 
// above compiles and works. You assign 'B b' to a `new B()`

class C extends A { }
C c = new B().first("hi"); 
// ClassCastException, but you can see that instantly. 'C c' gets assigned to 'new B()'

答案 1 :(得分:1)

我是这么认为的。你必须覆盖B中A的方法才能使它起作用。

public class B extends A{

    public B bfisrt(){
        System.out.println("asd");
        return this;
    }
    public B first(String s){  
        super.first( s );     
        return this;
    }   
    public B second(){
        super.second();
        return this;
    }
}

我没有对此进行测试(现在已经很晚了!)所以如果你需要的话,请仔细检查并使用它。

答案 2 :(得分:0)

您可以尝试投射

B b=new B(); ((B)b.first("unu").second()).bfisrt();

希望这有帮助, Keshava。

答案 3 :(得分:0)

找到解决方案:

public abstract class X<T extends X<T>> {

  public abstract T self();

  public T xFirst(){
      System.out.println("xxx");
      return self();
  } 
}  



public class Y extends X<Y>{    

   public Y yfirst(){
        System.out.println("yyy");  
        return self();
    }

  @Override
  public Y self() {     
        return this;
    }
   }  

并且在主链中可以使用忽略继承

 new Y().xFirst().yfirst().xFirst().yfirst();