【发布时间】:2014-05-27 19:01:21
【问题描述】:
在 java 中有什么需要这样的规则:
“子类不能削弱父类中定义的方法的可访问性”
【问题讨论】:
标签: java inheritance subclass superclass
在 java 中有什么需要这样的规则:
“子类不能削弱父类中定义的方法的可访问性”
【问题讨论】:
标签: java inheritance subclass superclass
class Person {
public String name() {
return "rambo";
}
}
// subclass reduces visibility to private
class AnonymousPerson {
private String name() {
return "anonymous";
}
}
使用Person 或AnonymousPerson 作为参数调用以下方法是合法的。但是,如果方法的可见性受到限制,它就无法调用name() 方法。
class Tester {
static void printPersonName(Person p) {
System.out.println(p.name());
}
}
//ok
Tester.printPersonName(new Person());
这个调用是合法的,因为Person 是AnonymousPerson,但它必须在方法体内失败。这违反了“类型安全”。
Tester.printPersonName(new AnonymousPerson());
【讨论】:
含义
子类方法的可见性不能比超类方法更严格。
例如,如果定义了超类
protected void a() { } // visible to package and subclasses
子类可以用其中之一覆盖它
public void a() { } // visible to all
protected void a() { } // visible to package and subclasses
但不是
void a() { } // visible to package
private void a() { } // visible to itself
为什么
假设定义是
class A {
public void a() { }
}
class B extends A {
private void a() { }
}
现在,考虑下面的代码
A instance = new B();
instance.a(); // what does this call?
一方面,任何B 都有一个可公开访问的a 方法。另一方面,B 实例的a 方法只能由B 访问。
更一般地说,子类(接口)必须履行其超类(接口)的契约。
可见性只是这一原则的一个例子。另一个例子是非抽象类必须实现它实现的任何接口的所有方法。
【讨论】:
如果你有一个带有公共方法的类
public class Foo {
public void method() {}
}
此方法是可访问的,因此您可以这样做
Foo foo = new Foo();
foo.method();
如果你添加一个子类
public class Bar extends Foo {
@Override
public /* private */ void method() {}
}
如果是private,你应该做不到
Foo bar = new Bar();
bar.method();
在此示例中,Bar 是 Foo,因此它必须能够替换 Foo 任何需要的位置。
为了满足上述陈述,子类不能使可继承成员的可访问性降低。但是,它可以使其更易于访问。 (这基本上只适用于方法。)
【讨论】:
履行接口契约。假设我有一个接口,IFlying,如下:
public interface IFlying {
public void fly();
}
我有一个削弱可访问性的实现:
public class Bird implements IFlying {
private void fly(){
System.out.println("flap flap");
}
}
我现在有一些接受 IFlying 的库函数,并在其上调用 fly。实现是私有的。现在会发生什么?当然,这意味着fly方法无法访问。
因此,可访问性在实现中可能不会受到更多限制。
【讨论】: