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() {

在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
        }
    }
}
现在我扩展这个类,如下所示:

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