@Override
public String toString() {
return super.super.toString();
}
我不确定它在许多情况下是否有用,但我想知道为什么它不是这样,并且其他语言中是否存在类似的东西。
你们觉得呢?
编辑: 澄清一下:是的,我知道在Java中这是不可能的,我也不是很想要它。这不是我期望它能工作,而是惊讶于得到编译器错误。我只是有这个想法,想讨论一下。
@Override
public String toString() {
return super.super.toString();
}
我不确定它在许多情况下是否有用,但我想知道为什么它不是这样,并且其他语言中是否存在类似的东西。
你们觉得呢?
编辑: 澄清一下:是的,我知道在Java中这是不可能的,我也不是很想要它。这不是我期望它能工作,而是惊讶于得到编译器错误。我只是有这个想法,想讨论一下。
我猜是因为它并不经常使用。唯一能想到使用它的原因是,如果你的直接父类覆盖了某些功能,并且你正在尝试将其恢复到原始状态。
这在我的看法中违反了面向对象的原则,因为类的直接父类应该比祖父类更与你的类相关。
class SuperSuperClass {
public String toString() {
return DescribeMe();
}
protected String DescribeMe() {
return "I am super super";
}
}
class SuperClass extends SuperSuperClass {
public String toString() {
return "I am super";
}
}
class ChildClass extends SuperClass {
public String toString() {
return DescribeMe();
}
}
如果您无法更改超级超类,则可以尝试以下方法:
class SuperSuperClass {
public String toString() {
return "I am super super";
}
}
class SuperClass extends SuperSuperClass {
public String toString() {
return DescribeMe(super.toString());
}
protected String DescribeMe(string fromSuper) {
return "I am super";
}
}
class ChildClass extends SuperClass {
protected String DescribeMe(string fromSuper) {
return fromSuper;
}
}
new ChildClass().toString();
结果为“我是超级超级”
public class A {
@Override
public String toString() {
return "A";
}
}
public class B extends A {
@Override
public String toString() {
return "B";
}
}
public class C extends B {
@Override
public String toString() {
return "C";
}
}
public class D extends C {
@Override
public String toString() {
String result = "";
try {
result = this.getClass().getSuperclass().getSuperclass().getSuperclass().newInstance().toString();
} catch (InstantiationException ex) {
Logger.getLogger(D.class.getName()).log(Level.SEVERE, null, ex);
} catch (IllegalAccessException ex) {
Logger.getLogger(D.class.getName()).log(Level.SEVERE, null, ex);
}
return result;
}
}
public class Main {
public static void main(String... args) {
D d = new D();
System.out.println(d);
}
}
运行: A 构建成功(总时间:0秒)
看起来至少可以使用反射获取超类的超类的类,虽然不一定是它的实例;如果这可能有用,请考虑查看Javadoc http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Class.html#getSuperclass()。
...
FrameworkBaseClass (....) extends...
{
methodA(...){...}
methodB(...){...}
...
methodX(...)
...
methodN(...){...}
}
/* CustomBaseClass overrides default framework functionality for benefit of several derived classes.*/
CustomBaseClass(...) extends FrameworkBaseClass
{
private boolean skipMethodX=false;
/* implement accessors isSkipMethodX() and setSkipMethodX(boolean)*/
methodA(...){...}
methodB(...){...}
...
methodN(...){...}
methodX(...){
if (isSkipMethodX()) {
setSKipMethodX(false);
super.methodX(...);
return;
}
... //common method logic
}
}
DerivedClass1(...) extends CustomBaseClass
DerivedClass2(...) extends CustomBaseClass
...
DerivedClassN(...) extends CustomBaseClass...
DerivedClassX(...) extends CustomBaseClass...
{
methodX(...){
super.setSKipMethodX(true);
super.methodX(...);
}
}
这非常容易。例如:
C 是 B 的子类,B 是 A 的子类。三个类都有一个方法 methodName()。
public abstract class A {
public void methodName() {
System.out.println("Class A");
}
}
public class B extends A {
public void methodName() {
super.methodName();
System.out.println("Class B");
}
// Will call the super methodName
public void hackSuper() {
super.methodName();
}
}
public class C extends B {
public static void main(String[] args) {
A a = new C();
a.methodName();
}
@Override
public void methodName() {
/*super.methodName();*/
hackSuper();
System.out.println("Class C");
}
}
运行类C,输出将为: 类A 类C
而不是输出: 类A 类B 类C
在我看来,这是一种在Java中实现super.super.sayYourName()
行为的简洁方式。
public class GrandMa {
public void sayYourName(){
System.out.println("Grandma Fedora");
}
}
public class Mama extends GrandMa {
public void sayYourName(boolean lie){
if(lie){
super.sayYourName();
}else {
System.out.println("Mama Stephanida");
}
}
}
public class Daughter extends Mama {
public void sayYourName(boolean lie){
if(lie){
super.sayYourName(lie);
}else {
System.out.println("Little girl Masha");
}
}
}
public class TestDaughter {
public static void main(String[] args){
Daughter d = new Daughter();
System.out.print("Request to lie: d.sayYourName(true) returns ");
d.sayYourName(true);
System.out.print("Request not to lie: d.sayYourName(false) returns ");
d.sayYourName(false);
}
}
输出:
请求说谎:d.sayYourName(true) 返回奶奶 Fedora
请求不说谎:d.sayYourName(false) 返回小女孩 Masha
我认为这是违反继承协议的问题。
通过扩展一个类,你遵守/同意它的行为和特性。
而当调用super.super.method()
时,你想要打破自己的服从协议。
你不能仅仅从超类中挑选。
然而,在你的代码或继承的代码中,可能会出现需要调用super.super.method()
的情况 - 这通常是一个不好的设计信号!
如果super和super super类无法重构(一些旧代码),那么选择组合而不是继承。
封装破坏是当你通过破坏封装的代码来@Override一些方法时发生的。
被设计为不可覆盖的方法被标记为final。
public class A
internal virtual void foo()
...
public class B : A
public new void foo()
...
public class C : B
public new void foo() {
(this as A).foo();
}
你也可以在Delphi中这样做:
type
A=class
procedure foo;
...
B=class(A)
procedure foo; override;
...
C=class(B)
procedure foo; override;
...
A(objC).foo();
但是在Java中,你可以通过一些小技巧来实现这种聚焦。其中一种可能的方式是:
class A {
int y=10;
void foo(Class X) throws Exception {
if(X!=A.class)
throw new Exception("Incorrect parameter of "+this.getClass().getName()+".foo("+X.getName()+")");
y++;
System.out.printf("A.foo(%s): y=%d\n",X.getName(),y);
}
void foo() throws Exception {
System.out.printf("A.foo()\n");
this.foo(this.getClass());
}
}
class B extends A {
int y=20;
@Override
void foo(Class X) throws Exception {
if(X==B.class) {
y++;
System.out.printf("B.foo(%s): y=%d\n",X.getName(),y);
} else {
System.out.printf("B.foo(%s) calls B.super.foo(%s)\n",X.getName(),X.getName());
super.foo(X);
}
}
}
class C extends B {
int y=30;
@Override
void foo(Class X) throws Exception {
if(X==C.class) {
y++;
System.out.printf("C.foo(%s): y=%d\n",X.getName(),y);
} else {
System.out.printf("C.foo(%s) calls C.super.foo(%s)\n",X.getName(),X.getName());
super.foo(X);
}
}
void DoIt() {
try {
System.out.printf("DoIt: foo():\n");
foo();
Show();
System.out.printf("DoIt: foo(B):\n");
foo(B.class);
Show();
System.out.printf("DoIt: foo(A):\n");
foo(A.class);
Show();
} catch(Exception e) {
//...
}
}
void Show() {
System.out.printf("Show: A.y=%d, B.y=%d, C.y=%d\n\n", ((A)this).y, ((B)this).y, ((C)this).y);
}
}
objC.DoIt() 的结果输出:
DoIt: foo():
A.foo()
C.foo(C): y=31
Show: A.y=10, B.y=20, C.y=31
DoIt: foo(B):
C.foo(B) calls C.super.foo(B)
B.foo(B): y=21
Show: A.y=10, B.y=21, C.y=31
DoIt: foo(A):
C.foo(A) calls C.super.foo(A)
B.foo(A) calls B.super.foo(A)
A.foo(A): y=11
Show: A.y=11, B.y=21, C.y=31
public class Foo
{
public int getNumber()
{
return 0;
}
}
public class SuperFoo extends Foo
{
public static Foo superClass = new Foo();
public int getNumber()
{
return 1;
}
}
public class UltraFoo extends Foo
{
public static void main(String[] args)
{
System.out.println(new UltraFoo.getNumber());
System.out.println(new SuperFoo().getNumber());
System.out.println(new SuperFoo().superClass.getNumber());
}
public int getNumber()
{
return 2;
}
}
2
1
0
new UltraFoo.getNumber()
无法编译,因为你错过了括号。然而,既然你的代码概念已经很清晰了,谢谢!我刚刚撤销了我的投票。 - Tim Büthe
super.super.toString()
与你选择扩展一个类并接受它的所有特性的决定相矛盾,因此不建议这样做。 - DayaMoon