Java 继承与此和超级
在Java中工作 我有一个抽象类:Java 继承与此和超级,java,inheritance,Java,Inheritance,在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() {
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
}
}
}
现在我扩展这个类,如下所示:
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
}
}
}
问题:
我的Bar.class实际上是指super.log
,尽管我调用这个.log
,因为Bar没有自己的局部变量log
?或者实现isLoggerSet()
方法的正确方法是将其抽象化,并强制Bar.class在其log
的本地副本上实现它自己,因为它已被扩展
基本上,我必须在我的Foo类中说
this.log
,因为它指的是它自己。但是在Bar类中,我希望能够空检查log
,我是否应该在Bar.class中使用super.log=
?如果类层次结构中只有一个名为log
的属性,那么无论你说this.log
还是super.log
,它都会引用同一个属性,即唯一的属性 您没有将记录器设置为静态
,而是设置为受保护
。
无论您使用的是
super
还是this
,它们都指向本例中完全相同的变量。this.log
与super.log
相同。只有一个变量,因为log
是从Foo继承的。
只需要一个更改:this.isLoggerSet()
应替换为b.isLoggerSet()
不能在静态方法中调用非静态方法这里是一个稍加修改的示例:
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
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
所以有两个变量叫做“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
super.name=Mr. Foo
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的默认构造函数。类是创建对象的蓝图。在您的例子中,“Bar”的蓝图添加到“Foo”中定义的蓝图上(它添加到“Object”中定义的蓝图上) 不要让基类迷惑您:从概念上讲,编译器将所有基类拉入一个顶级组合类(忽略“对象”基类): 您可以这样练习代码:
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()”也将传递到这里。只有一个
log
属性。不过,一般来说,您不需要实例拥有自己的记录器;通常,如果(this.isLoggerSet())无法在静态上下文中编译,则它们是public static final
。如果我尝试空检查的不是记录器,这是否仍然适用?我只是使用了记录器,因为这就是我手头的示例。@Eng.Fouad抱歉,这是我从代码库中输入的一个快速示例。。。我现在就解决这个问题。someMethod只能在Bar的实例上调用。在someMethod中创建了一个新的Bar实例。所以在这个例子中肯定有两个例子,我认为这不是你想要的。日志示例使问题变得不清楚,因为日志记录器通常是静态的。因此,如果我理解正确,在抽象类和扩展类的构造函数中初始化一个变量,会导致两个单独的变量,name
?