问题
我读了this question并且认为如果可以写的话很容易解决(不是没有它可以解决):
@Override
public String toString() {
return super.super.toString();
}
我不确定它在许多情况下是否有用,但我不知道为什么不是,如果在其他语言中存在这样的东西。
你们有什么感想?
**编辑:**澄清:是的我知道,这在Java中是不可能的,我不会真的错过它。这不是我期望的工作,并且惊讶于编译错误。我刚才有了这个想法并想讨论它。
#1 热门回答(434 赞)
它违反了封装。你不应该绕过父类的行为。有时候能够绕过你的类的行为(特别是在同一个方法中)而不是你父母的行为是有意义的。例如,假设我们有一个基础"项目集合",一个表示"红色项目集合"的子类,以及表示"大红色项目集合"的子类。有:有意义:
public class Items
{
public void add(Item item) { ... }
}
public class RedItems extends Items
{
@Override
public void add(Item item)
{
if (!item.isRed())
{
throw new NotRedItemException();
}
super.add(item);
}
}
public class BigRedItems extends RedItems
{
@Override
public void add(Item item)
{
if (!item.isBig())
{
throw new NotBigItemException();
}
super.add(item);
}
}
没关系 - RedItems总能确信它包含的项目都是红色的。现在假设我们可以调用super.super.add():
public class NaughtyItems extends RedItems
{
@Override
public void add(Item item)
{
// I don't care if it's red or not. Take that, RedItems!
super.super.add(item);
}
}
现在我们可以添加任何我们喜欢的东西,并且RedItems
中的不变量被破坏了。
那有意义吗?
#2 热门回答(61 赞)
我认为Jon Skeet有正确的答案。我想通过castthis
添加你可以从超类的超类中获取阴影变量:
interface I { int x = 0; }
class T1 implements I { int x = 1; }
class T2 extends T1 { int x = 2; }
class T3 extends T2 {
int x = 3;
void test() {
System.out.println("x=\t\t" + x);
System.out.println("super.x=\t\t" + super.x);
System.out.println("((T2)this).x=\t" + ((T2)this).x);
System.out.println("((T1)this).x=\t" + ((T1)this).x);
System.out.println("((I)this).x=\t" + ((I)this).x);
}
}
class Test {
public static void main(String[] args) {
new T3().test();
}
}
产生输出:
x= 3
super.x= 2
((T2)this).x= 2
((T1)this).x= 1
((I)this).x= 0
(来自JLS的例子)
但是,这不适用于方法调用,因为方法调用是根据对象的运行时类型确定的。
#3 热门回答(37 赞)
我认为以下代码允许在大多数情况下使用super.super ... super.method()。 (即使这样做很可取)
简而言之
- 创建祖先类型的临时实例
- 将原始对象的字段值复制到临时对象
- 在临时对象上调用目标方法
- 将修改后的值复制回原始对象
用法:
public class A {
public void doThat() { ... }
}
public class B extends A {
public void doThat() { /* don't call super.doThat() */ }
}
public class C extends B {
public void doThat() {
Magic.exec(A.class, this, "doThat");
}
}
public class Magic {
public static <Type, ChieldType extends Type> void exec(Class<Type> oneSuperType, ChieldType instance,
String methodOfParentToExec) {
try {
Type type = oneSuperType.newInstance();
shareVars(oneSuperType, instance, type);
oneSuperType.getMethod(methodOfParentToExec).invoke(type);
shareVars(oneSuperType, type, instance);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
private static <Type, SourceType extends Type, TargetType extends Type> void shareVars(Class<Type> clazz,
SourceType source, TargetType target) throws IllegalArgumentException, IllegalAccessException {
Class<?> loop = clazz;
do {
for (Field f : loop.getDeclaredFields()) {
if (!f.isAccessible()) {
f.setAccessible(true);
}
f.set(target, f.get(source));
}
loop = loop.getSuperclass();
} while (loop != Object.class);
}
}