Java 不带重写的子类(别名类)

Java 不带重写的子类(别名类),java,subclass,Java,Subclass,如果我有一个具体的类Foo,我想添加一个名为Bar的“别名”,它扩展Foo,但不覆盖任何方法,Java会允许我这样做吗 编辑:上下文-目标是最终将Foo重命名为Bar,因为Foo的名称很差;但是,Foo依赖于另一个项目,我不能在同一个提交中同时更改Foo和FooCaller。为了避免破坏FooCaller,我将做三个更改:(1)添加Bar,(2)将FooCaller更改为BarCaller(相同行为),(3)完全删除Foo(当不再有FooCaller时) 这里是否有陷阱,或者Bar的行为是否与F

如果我有一个具体的类
Foo
,我想添加一个名为
Bar
的“别名”,它扩展
Foo
,但不覆盖任何方法,Java会允许我这样做吗

编辑:上下文-目标是最终将
Foo
重命名为
Bar
,因为
Foo
的名称很差;但是,
Foo
依赖于另一个项目,我不能在同一个提交中同时更改
Foo
FooCaller
。为了避免破坏
FooCaller
,我将做三个更改:(1)添加
Bar
,(2)将
FooCaller
更改为
BarCaller
(相同行为),(3)完全删除
Foo
(当不再有
FooCaller
时)


这里是否有陷阱,或者
Bar
的行为是否与
Foo
相同?

只要使用适当的可见性,Bar的行为将与Foo相同。Bar将无法访问Foo中的私有方法和属性,受保护的方法和属性将假定为Bar中的私有方法和属性

下面的示例将向控制台输出“Foo”

class Example
{
    public static void main (String[] args)
    {
        Bar b = new Bar();
        System.out.println(b.getName());
    }
}

class Foo {
    protected String name; // Will be private in Bar

    public Foo() {
        this.name = "Foo";
    }

    public String getName() {
        return this.name;
    }
}

class Bar extends Foo {

}

是的,Java允许您对非
final
concrete类进行子类化,只是为了给原始类添加别名

public class Foo {  /* implementation */ }

public class Bar extends Foo {}
假设
Foo
中只有一个默认构造函数,那么这将是最小的实现。如果有构造函数在
Foo
中接受参数,则必须在
Bar
中为您计划调用以创建
Bar
实例的每个构造函数提供一个构造函数,例如:

public class Foo {
    public Foo(String baz) { /* constructor implementation */ }
}

public class Bar extends Foo {
    public Bar(String baz) { super(baz); }
}
Foo
中的所有非
private
方法将由
Bar
继承

它可能不起作用的唯一地方是,如果您打算使用
Bar
代替
Foo
作为泛型类型参数

例如,如果将
列表
替换为
列表
,则您的
列表
不能再包含任何
Foo
实例,或可能扩展
Foo
的任何其他类的实例


此外,由于Java的泛型是不变的,
列表
不是
列表
的子类型,即使
Foo
。有关原因的详细信息,请参阅。此外,如果您使用
list,您可能可以绕过它。我认为您需要注意构造函数,但是没有义务重写父类的任何方法,除非父类是抽象的。您是否将
Foo
Bar
用作泛型类型参数,例如,
列表
?@targetman不只是一个渐进重构的别名,
Foo
Bar
之间不应该有任何功能上的区别。但是,我想您不会介意它可能导致的设计混乱(如果它不添加任何附加功能,为什么
Bar
extend
Foo
)。此外,依赖getClass()的代码可能会表现不同。泛型问题是一个很好的观点。在我的特殊情况下,目标是最终将Foo重命名为Bar,因为Foo的名称很差;然而,Foo依赖于另一个项目,我不能在同一个提交中同时更改Foo和FooCaller。为了避免破坏FooCaller,我将做三个更改:(1)添加Bar,(2)将FooCaller更改为BarCaller(相同的行为),(3)完全删除Foo。@mfrankli这是一个很好的上下文,可以包含在您的问题中。我建议将Foo重命名为Bar,然后创建一个新的Foo来扩展Bar以实现向后兼容性。