繁体   English   中英

在Java中更改继承的成员变量的数据类型的正确方法是什么?

[英]What is the Proper way to Change the Data Type of an Inherited Member Variable in Java?

编辑:快速背景:Foo是一个抽象类,其唯一目的是减少成员变量声明中的冗余。 它没有方法(除了mutator和accessor之外)或显式构造函数。

我试图“重写”从父级继承的成员变量的数据类型。 这对我来说似乎不合法。

import org.joda.time.DateTime;
import java.util.Date;

public abstract class Foo {
    private Date dt;
    public Date getDt() {
        return dt;
    }
}
public class Bar extends Foo {

}
public class Baz extends Foo {
    private DateTime dt;        //this is legal
    //causes: The return type is incompatable with Foo.getDt()
    public DateTime getDt() {   
        return dt;
    }
}

我注意到,我可以在继承的类中声明一个具有相同名称的不同类型的变量,但是我不能声明一个访问器方法,该方法在继承的类中返回的类型不同于在父类中的返回类型。

我是否应该忘记合同,并且这样做吗?

public abstract class Foo {
}

public class Bar extends Foo {
    private Date dt;
    public Date getDt() {
        return dt;
    }
}

public class Baz extends Foo {
    private DateTime dt;
    public DateTime getDt() {
        return dt;
    }
}

还是最好使父级的成员变量的数据类型为Object ,并在父级中放置访问器和mutator,而不在子级中创建任何相应的成员变量?

public abstract class Foo {
    private Object dt;
    public Object getDt() {
        return dt;
    }
    public void setDt(Object dt) {
        this.dt = dt;
    }
}
public class Bar extends Foo {
}
public class Baz extends Foo {
}

出于同样的想法,这是否比上面更好?

public class Baz extends Foo {
    public DateTime getDt() {
        return (DateTime) super.getDt();
    }
}

最好/最合适的方法是什么?

您是否有调用者以Foo的引用类型调用getDt()

如果不是,则getDt()不应该是Foo的成员; 它应该在子类中或根本不存在。

如果您这样做,那么该呼叫者期望什么返回类型? 那是您应该使用的类型。

编写API是为了支持应用程序。 应用程序未编写为使用API​​。 您的应用程序对Foo什么要求?

由于类美孚宣布的返回类型getDt()Date ,该方法的任何重载情况下,必须返回日期或子类Date 在您提出的解决方案中,#2更有意义,因为您将返回Object两个不同的子类,但是我认为这种设计选择不太理想。 让我解释。

为了处理这样的设计选择,任何在Foo或其子类上调用getDt()方法都必须执行以下类似操作来确定如何查询结果:

Object date = Baz.getDt();
if (date instanceof Date) {
    ...
} else if (date instanceof DateTime) { 
    ...
} else {
    ...
}

通常,if / elseif块和instanceof的组合是一个坏主意。

更好的主意是建立一个称为FooDate的通用对象。 Foo类中,可以定义getDt()方法以返回FooDate对象:

public class Foo {

    FooDate fooDate = null;

    public FooDate getDt() {
        return fooDate;
    }
}

然后,每个子类可以采用不同的构造函数:

Bar(Date date) {
    //set fooDate
}

Baz(DateTime dateTime) {
    //set fooDate
}

FooDate类型将存储您拥有子类的每个与日期相关的潜在类型中您关心的数据,然后在构造函数中进行类型询问,并返回一个可以使用的一致类型,而无需if / elseif带有instanceof检查的块。

编辑:随着Foo是抽象的启示,顺应埃里克森的回答。 在这种情况下,他的更为适用。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM