用这个和超级继承

时间:2013-05-21 19:10:32

标签: 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() {
        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 =吗?

5 个答案:

答案 0 :(得分:3)

您尚未将记录器设置为static,而是设置为protected。 无论您使用super还是this,在这种情况下,它们都指向完全相同的变量。

答案 1 :(得分:2)

如果类层次结构中只有一个名为log的属性,那么如果您说this.logsuper.log并不重要,它将引用同一个 - 唯一一个!

答案 2 :(得分:2)

this.logsuper.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的默认构造函数。