方法链接+继承不能很好地结合在一起? [英] Method chaining + inheritance don’t play well together?

查看:119
本文介绍了方法链接+继承不能很好地结合在一起?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

此问题已在C ++环境中提出但我对Java很好奇。关于虚拟方法的担忧不适用(我认为),但如果您遇到这种情况:

This question has been asked in a C++ context but I'm curious about Java. The concerns about virtual methods don't apply (I think), but if you have this situation:

abstract class Pet
{
    private String name;
    public Pet setName(String name) { this.name = name; return this; }        
}

class Cat extends Pet
{
    public Cat catchMice() { 
        System.out.println("I caught a mouse!"); 
        return this; 
    }
}

class Dog extends Pet
{
    public Dog catchFrisbee() { 
        System.out.println("I caught a frisbee!"); 
        return this; 
    }
}

class Bird extends Pet
{
    public Bird layEgg() {
        ...
        return this;
    }
}


{
    Cat c = new Cat();
    c.setName("Morris").catchMice(); // error! setName returns Pet, not Cat
    Dog d = new Dog();
    d.setName("Snoopy").catchFrisbee(); // error! setName returns Pet, not Dog
    Bird b = new Bird();
    b.setName("Tweety").layEgg(); // error! setName returns Pet, not Bird
}

在这种类层次结构中,有没有以某种方式返回的方式是否(有效地)向上转换对象类型?

In this sort of class hierarchy, is there any way to return this in a way that doesn't (effectively) upcast the the object type?

推荐答案

如果你想避免编译器的未经检查的强制警告(并且不想@SuppressWarnings(未选中)),那么你需要做更多的事情:

If you want to avoid unchecked cast warnings from your compiler (and don't want to @SuppressWarnings("unchecked")), then you need to do a little more:

首先,你对Pet的定义必须是自我指涉的,因为Pet总是一般类型:

First of all, your definition of Pet must be self-referential, because Pet is always a generic type:

abstract class Pet <T extends Pet<T>>

其次,(T)此演员表在setName中也未选中。为了避免这种情况,请在优秀的 Angelika Langer的Generics FAQ中使用getThis技术

Secondly, the (T) this cast in setName is also unchecked. To avoid this, use the "getThis" technique in the excellent Generics FAQ by Angelika Langer:


getThis技巧提供了一种方法
恢复这个
的确切类型参考。

The "getThis" trick provides a way to recover the exact type of the this reference.

这导致下面的代码编译并在没有警告的情况下运行。如果你想扩展你的子类,那么这个技术仍然存在(尽管你可能需要对你的中间类进行泛化)。

This results in the code below, which compiles and runs without warnings. If you want to extend your subclasses, then the technique still holds (though you'll probably need to genericise your intermediate classes).

结果代码是:

public class TestClass {

  static abstract class Pet <T extends Pet<T>> {
    private String name;

    protected abstract T getThis();

    public T setName(String name) {
      this.name = name;
      return getThis(); }  
  }

  static class Cat extends Pet<Cat> {
    @Override protected Cat getThis() { return this; }

    public Cat catchMice() {
      System.out.println("I caught a mouse!");
      return getThis();
    }
  }

  static class Dog extends Pet<Dog> {
    @Override protected Dog getThis() { return this; }

    public Dog catchFrisbee() {
      System.out.println("I caught a frisbee!");
      return getThis();
    }
  }

  public static void main(String[] args) {
    Cat c = new Cat();
    c.setName("Morris").catchMice();
    Dog d = new Dog();
    d.setName("Snoopy").catchFrisbee();
  }
}

这篇关于方法链接+继承不能很好地结合在一起?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆