2013-05-21 5 views
0

Работа на 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 потому что у Бар нет собственной локальной переменной log? Или был бы правильным способом реализовать метод isLoggerSet(), чтобы сделать его абстрактным и заставить Bar.class реализовать его сам на своей локальной копии log, поскольку он был расширен?

В принципе, я должен сказать this.log в моем классе Foo, потому что он относится к самому себе. Но в классе Bar я хочу, чтобы иметь возможность проверить null log, следует ли вместо этого использовать super.log = в Bar.class?

+1

Существует только одно свойство 'log'. В общем, вам не нужны экземпляры, чтобы иметь свой собственный регистратор; обычно они являются «публичным статическим окончанием». –

+0

'if (this.isLoggerSet())' не будет компилироваться в статическом контексте. –

+0

Используется ли это, если это не «Логгер», который я пытаюсь «проверить нуль»? Я просто использовал регистратор, потому что это был пример. – SnakeDoc

ответ

3

У вас не установлен ваш регистратор на static, но вместо этого на protected. Используете ли вы super или this, они указывают на ту же самую переменную в этом случае.

2

Если в иерархии классов есть только один атрибут log, не имеет значения, скажете вы this.log или super.log, это будет ссылка на тот же самый - единственный!

2

this.log - тот же super.log. Существует только одна переменная, потому что log наследуется от Foo. Требуется только одно изменение: this.isLoggerSet() следует заменить b.isLoggerSet() Вы не можете назвать нон статический метод в статический метод

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 

Итак, есть две переменные, называемые «имя», по одному в каждом классе. Чтобы получить доступ к тому, что находится в суперклассе из подкласса, вам нужно использовать «super.name».

При создании бара() 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 не вызывается в этом последнем примере.

+0

Итак, если я правильно понимаю это, имея переменную, инициализированную в конструкторе как для абстрактного, так и для расширенного классов, приводит к двум отдельным переменным: 'name' в этом случае? – SnakeDoc

+0

См. Мои добавления –

2

Классы - чертежи для создания объектов. В вашем случае план «Бар» добавляет к чертежу, определенному в «Foo» (который добавляет к проекту, определенному в «Объекте»).

Не позволяйте BaseClass вас смущать: концептуально здесь компилятор тянет все базовые классы вверх в один верхнего уровня комбинированного класса (не обращая внимания на «Объект» базы):

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); 

Первая строка создает новый объект типа «Бар» в памяти. Этот объект имеет единственный указатель на объект «Logger», который устанавливается в конструкторе Bar в первой строке с помощью «new Bar()».

Следующая строка проверяет «isLoggerSet». Предполагая, что «getLogger» возвращает живой объект, тогда «isLoggerSet» всегда будет возвращать true.

Последняя строка вызывает «x.someMethod (args)». Этот метод создает новый объект «Bar» (конструктор которого устанавливает свой «лог»). Таким образом, здесь и «b.isLoggerSet()».

Смежные вопросы