使用Java。
我有一个抽象类:
public abstract class Foo {
protected Logger log = null;
// other stuff
public boolean isLoggerSet() {
return (this.log != null) ? true : false;
}
}
现在我这样扩展这个类:
public class Bar extends Foo {
public Bar() {
this.log = Logger.getLogger(Bar.class);
}
public void someMethod(String[] args) {
Bar b = new Bar();
if(b.isLoggerSet()) {
// do some stuff
}
}
}
The question:
我的Bar.class实际上指的是super.log
,即使我调用this.log
,因为Bar没有自己的局部变量log
?或者,实现isLoggerSet()
方法的正确方法是将其抽象化并强制Bar.class在log
的本地副本上实现它,因为它已经被扩展了吗?
基本上我必须在我的Foo类中说this.log
,因为它指的是它自己。但是在Bar类中我希望能够对log
进行空检查,我应该在Bar.class中使用super.log =
吗?
答案 0 :(得分:3)
您尚未将记录器设置为static
,而是设置为protected
。
无论您使用super
还是this
,在这种情况下,它们都指向完全相同的变量。
答案 1 :(得分:2)
如果类层次结构中只有一个名为log
的属性,那么如果您说this.log
或super.log
并不重要,它将引用同一个 - 唯一一个!
答案 2 :(得分:2)
this.log
与super.log
相同。只有一个变量,因为log
是从Foo继承的。
只需进行一项更改:this.isLoggerSet()
应替换为b.isLoggerSet()
你不能在静态方法中调用非静态方法
答案 3 :(得分:2)
类是制作对象的蓝图。在您的情况下,“Bar”的蓝图会添加到“Foo”中定义的蓝图(这将添加到“Object”中定义的蓝图)。
不要让基类混淆你:概念这里编译器将所有基类拉到一个顶级组合类中(忽略“对象”基础):
public class Bar {
protected Logger log = null;
public boolean isLoggerSet() {
return (log != null) ? true : false;
}
public Bar() {
log = Logger.getLogger(Bar.class);
}
public void someMethod(String [] args) {
Bar b = new Bar();
if(b.isLoggerSet()) {
// do some stuff
}
}
}
你会像这样运用你的代码:
Bar x = new Bar();
x.isLoggerSet(); // Returns true since Bar() constructor just set it
x.someMethod(args);
第一行在内存中创建一个类型为“Bar”的新对象。该对象有一个指向“Logger”对象的指针,该对象在第一行的Bar构造函数中设置为“new Bar()”。
下一行检查“isLoggerSet”。假设“getLogger”返回一个活动对象,那么“isLoggerSet”将始终返回true。
最后一行称为“x.someMethod(args)”。此方法创建一个新的“Bar”对象(其构造函数设置其“log”指针)。因此“b.isLoggerSet()”也会在这里传递。
答案 4 :(得分:1)
这是一个略微修改的例子:
public abstract class Foo {
protected String name;
public Foo() {
name = "Mr. Foo";
}
}
public class Bar extends Foo {
protected String name;
public Bar() {
name = "Mr. Bar";
}
public void someMethod() {
System.out.println("this.name=" + this.name);
System.out.println("super.name=" + super.name);
}
public static void main(String[] args) {
Bar bar = new Bar();
bar.someMethod();
}
}
输出:
this.name=Mr. Bar
super.name=Mr. Foo
所以有两个变量名为'name',每个类一个。要从子类中访问超类中的那个,您需要使用'super.name'。
创建Bar()时,Java会检查对超类构造函数的超级(...)调用,作为构造函数的第一行。如果它不存在(如上所述)那么'super();'被无形插入作为构造函数的第一行。所以我可以写:
....
public Bar() {
super();
name = "Mr. Bar";
}
....
结果相同。但是,这不是必需的,如果您不自己调用超级构造函数,Java会为您插入对默认构造函数的超级调用。以这种方式强制执行构造函数链接。
如果你想自己调用超级构造函数,你也可以调用非默认构造函数,例如:
public abstract class Foo {
protected String name;
public Foo() {
name = "Mr. Foo";
}
public Foo(String name) {
this.name = name;
}
}
public class Bar extends Foo {
public Bar() {
super("Mr. Bar");
}
public void someMethod() {
System.out.println("this.name=" + this.name);
System.out.println("super.name=" + super.name);
}
public static void main(String[] args) {
Bar bar = new Bar();
bar.someMethod();
}
}
输出:
this.name=Mr. Bar // refers to 'name' inherited from Foo
super.name=Mr. Bar // refers to 'name' in superclass, set by the String constructor
// so these both refer to the same variable in this example
注意在最后一个例子中没有调用Foo的默认构造函数。