如果我有一个具体的类Foo
,并且我想添加一个名为Bar
的“别名”,它扩展Foo
但不覆盖任何方法 - 请Java让我这样做?
修改:上下文 - 目标是最终将Foo
重命名为Bar
,因为Foo
命名不佳;但是,Foo
依赖于另一个项目,我无法在同一次提交中更改Foo
和FooCaller
。为避免中断FooCaller
,我将进行三项更改:(1)添加Bar
,(2)将FooCaller
更改为BarCaller
(相同行为),(3)删除完全Foo
(当没有FooCaller
s时)。
此处是否存在问题,或Bar
的行为是否与Foo
完全相同?
答案 0 :(得分:1)
只要您使用适当的可见性,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 {
}
答案 1 :(得分:1)
是的,Java将允许您将非final
具体类子类化,仅用于对原始类进行别名。
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); }
}
private
中的所有非Foo
方法都将由Bar
继承。
唯一可能无效的地方是,如果您打算使用Bar
代替Foo
作为通用类型参数。
例如,如果您将List<Foo>
替换为List<Bar>
,那么您的List
将无法再容纳任何Foo
个实例或任何其他类的实例延长Foo
。
此外,由于Java的泛型是不变的,List<Bar>
不是List<Foo>
的子类型,即使Bar
是{ {1}}。有关案例原因的详细信息,请参阅Is List a subclass of List? Why aren't Java's generics implicitly polymorphic?。此外,如果您使用Foo
,则可以绕过它,以便您可以使用List<? extends Foo>
或List<Foo>
,但之后您将无法{{}除了List<Bar>
之外的其他任何内容。
您声明您不会在泛型中使用它,但如果您的要求得到扩展,请记住这一点。
总之,是的,Java编译器会允许你这样做,但有一个有限的优势 - 使用add
而不是null
作为别名 - 并且潜在的缺点,我看不到使用此别名过程的原因。