泛型子类化-构造函数继承

时间:2018-07-14 13:08:59

标签: java generics inheritance constructor

我试图创建一个用于表示变量的类,所以我首先创建了一个参数化的基类:

public abstract class DataField<Type>
{

    public enum DataTypes
    {
        STRING,
        INT,
        FLOAT,
        TIME,
        DATE
    }

    private DataTypes type=null;
    private String name=null;
    private Type value=null;

    private DataField()
    {
    }

    public DataField(String name)
    {
        setName(name);
    }

    DataField(String name, DataTypes type)
    {
        this(name);
        setType(type);
    }

    DataField(String name, DataTypes type, Type value)
    {
        this(name, type);
        setValue(value);
    }

    public DataField(String name, Type value)
    {
        this(name);
        setValue(value);
    }
    public DataField(String name, String value)
    {
        this(name);
        setStringValue(value);
    }
    public abstract void setStringValue(String strValue);
     ...
}

然后为不同类型制作的小节,定义了方法:

public class DataFieldInt extends DataField<Long>
 ...
public class DataFieldBoolean extends DataField<Boolean>
 ...

以此类推。但是我对String有一个预期的问题: 通用超级类有2个构造函数 DataField(String name, Type value)设置变量的名称和值,以及 DataField(String name, String value)可以从String设置变量的名称和值,并将其转换为所需的类型。但是对于子类,我有一个问题-使用什么构造函数,因为它们都将是(String,String)。因此,此代码

public class DataFieldString extends DataField<String>
{
    public DataFieldString(String name, String value)
    {
        super(name, value);
           ...
    }

给出有关歧义引用的错误 如何解决呢?我看到的唯一方法是使用StringBuilder或StringBuffer之类的东西来代替String,但有趣的是,有没有“本机”解决方案?

谢谢

1 个答案:

答案 0 :(得分:1)

  

如何解决?

通过提供对编译器没有任何歧义的调用。

  

我看到的唯一方法是使用StringBuilder或   用StringBuffer代替String,但是很有趣,是否有一个   “本地”解决方案?

它可以工作,但依赖String的构建器来传达不需要构建的 String 似乎也很笨拙。

注释中建议使用Factory的想法并不坏,但是根据您的设计,我认为它将需要进行许多更改并使您脱离实际设计:类的层次结构依赖于基类。
因为要使类之间的内容保持一致,您应该在每个子类中定义工厂。
此外,如果将两个构造函数保留在基类中,它将无法解决您的歧义问题。因此,您可能应该允许子类访问基类字段以执行构造函数逻辑。

因此,为了与您的实际设计保持一致,我将通过引入一个包装了TypeString变量的新类来解决歧义问题。
您可以在DataField类中声明该类:

static class NameAndType<Type> {
    private String name;
    private Type value;
    public NameAndType(String name, Type value ){
       ....
    }
}

因此DataField类可以公开这两个构造函数:

public DataField(NameAndType<Type> nameAndType) {
    this(nameAndType.name);
    setValue(nameAndType.value);
}

public DataField(String name, String value) {
    this(name);
    setStringValue(value);
}

这样,您可以在DataFieldString中公开一个依赖于基类构造函数之一的构造函数:

public class DataFieldString extends DataField<String> {

    public DataFieldString(String name, String value) {
        super(name, value);
        //  or the other way : super(new NameAndType<>(name, value));
    }    
   ...
}

其他子类可以根据基类构造函数提出两个构造函数。
例如:

public class DataFieldInt extends DataField<Integer> {

    public DataFieldInt(String name, Integer value) {
        super(new NameAndType<>(name, value));
    }

    public DataFieldInt(String name, String value) {
        super(name, value);
    }

    ...
}

这些类的客户端看不到NameAndType的复杂性/用法:

DataFieldInt dataFieldIntOne = new DataFieldInt("var1", 321);
DataFieldInt dataFieldIntTwo = new DataFieldInt("var1", "321");
DataFieldString dataFieldString = new DataFieldString("var1", "321");