链接,返回基础对象以及与扩展类的类型不匹配 [英] Chaining, returning base objects, and type mismatch to extended classes

查看:63
本文介绍了链接,返回基础对象以及与扩展类的类型不匹配的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我遇到过这样的课程.它具有"with"方法,该方法可以使人们将事物链接在一起.

I have come across a class like this. It holds a "with" method that lets people chain things together.

public class Bear {
    protected List<String> names = new ArrayList<String>();
    protected List<String> foods = new ArrayList<String>();

    public Bear withName(String name) {
        names.add(name);
        return this;
    }

    public Bear withFood(String food) {
        foods.add(food);
        return this;
    }
}

// ...somewhere else
Bear b = new Bear().withName("jake").withName("fish");

我发现两个类共享90%的相同代码.因此,我在它们之间创建了一个基类,并将25个左右的"with"方法(包括成员变量和全部)传递给它.

I found two classes that shared 90% of the same code. So, I created a base class between them, and transferred the 25 or so "with" methods to it (with the member variables and all.) Like so:

public abstract class Animal {
    protected List<String> names = new ArrayList<String>();

    public Animal withName(String name) {
        names.add(name);
        return this;
    }
}

public class Bear extends Animal {
    protected List<String> foods = new ArrayList<String>();

    public Bear withFood(String food) {
        foods.add(food);
        return this;
    }
}

但是,这现在破坏了一切(并且有很多地方在这两个类的设计中都使用了此功能.

However, this now breaks everything (And there is a lot of places that use this with design for these two classes).

Bear b = new Bear().withName("jake"); // Breaks
bear b2 = new Bear().withFood("fish"); // Fine

给出的错误:

类型不匹配:无法从动物转换为熊

Type mismatch: cannot convert from Animal to Bear

显然,当您返回基类this时,它返回的是Bear类型,并且不执行任何自动转换.

Apparently, when you return the base class this, it's returning a Bear type, and does not do any sort of automatic conversion.

我有什么解决/绕过此问题的选择?

What are my options to solve/bypass this issue?

推荐答案

您正在寻找 CRTP :

public abstract class Animal<T extends Animal<T>> {
    protected List<String> names = new ArrayList<String>();

    public T withName(String name) {
        names.add(name);
        return (T)this;
    }
}

这将产生不可避免的未经检查的强制转换警告,因为类型系统无法阻止您编写class Cat extends Animal<Dog> {} class Dog extends Animal<Dog>.

This will give an unavoidable unchecked cast warning, since the type system cannot prevent you from writing class Cat extends Animal<Dog> {} class Dog extends Animal<Dog>.

如果基类中有多个构建器方法,则可以通过编写private T returnThis() { return (T)this; }隔离警告.

If you have multiple builder methods in the base class, you can isolate the warning by writing private T returnThis() { return (T)this; }.

这篇关于链接,返回基础对象以及与扩展类的类型不匹配的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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