используя конструктор из суперкласса - PullRequest
1 голос
/ 06 января 2009

Java не допускает множественное наследование, что означает, что класс не может наследоваться от двух классов, которые не имеют ничего общего, что означает, что они не находятся на одном и том же пути наследования. Однако класс может наследовать от нескольких классов, если эти классы являются суперклассами прямого суперкласса класса. Но класс наследует от этих классов косвенно, что означает, что он ничего не «видит» от этих верхних суперклассов, верно? Я был сбит с толку при рассмотрении конструкторов (используя super () в конструкторе). Например, если у нас есть следующие классы:

public class A {
    public A() { 
      .... 
    }
}

public class B extends A {
    public B() {
      super();
      ....
    }
}

public class C extends B {
    public C() {
      super();
      ....
   }
}

конструктор класса C сначала вызывает конструктор класса B, используя super (). Когда это происходит, конструктор B сам вызывает сначала конструктор A (с super ()), но конструктор C ничего не знает о конструкторе A, верно? Я имею в виду, что наследование происходит только от прямого суперкласса - первого (ближайшего) класса из иерархии наследования. Это мой вопрос - под super () мы подразумеваем только конструктор прямого суперкласса, независимо от того, сколько других классов у нас в иерархии наследования. И это касается не только конструкторов, но и любых методов и переменных экземпляра.

Привет

Ответы [ 5 ]

4 голосов
/ 06 января 2009

Даже если вы могли бы избегать вызова промежуточного ctor, вы бы этого не хотели, потому что это означало бы, что у вас есть неинициализированные части промежуточных классов, к которым может обращаться самый нижний производный класс. К ужасным последствиям.

Но я чувствую, что вы пытаетесь обмануть Java, чтобы сделать множественное наследование. Это плохо. Вместо этого вы можете сделать это с помощью интерфейса Java

class B extends A implements C {
    // ... implement C methods here
}

или с помощью агрегации

class B extends A {
    private C c;
}
4 голосов
/ 06 января 2009

Вы должны вызвать некоторый конструктор в вашем непосредственном базовом классе. Это может быть

public class A {
     public A() { 
      .... 
     }
    public A(String foo) { 
      .... 
    }
}

public class B extends A {
    public B() {
        super();
        .. or ..
        super("ThisIsAB")
    }
}

public class C extends B {
    public C() {
      super();
      ....
   }
}

Так что для конструкторов вы не можете ИЗБЕЖАТЬ конструирования промежуточных базовых классов, но вы можете выбрать, какой конструктор использовать. Если есть только конструктор без аргументов, он обрабатывается для вас неявным вызовом super. С несколькими конструкторами у вас есть еще несколько вариантов.

super может ссылаться на любую не закрытую переменную или метод в любом базовом классе. Таким образом, методы и переменные в этом отношении не совпадают с конструкторами.

3 голосов
/ 06 января 2009

Конструкторы для всех родителей называются. Фактически, в глубине C знает об A, потому что B расширяет A. Например, если класс A содержит метод foo (), то вы можете вызвать foo () из C.

Итак, из вашего примера C вызывает конструктор из B, который вызывает конструктор из A. Кроме того, A также продолжается от класса Object. Поэтому конструктор в классе Object также называется!

Кроме того, вам не нужно добавлять вызов в super (). Если нет вызова для конструктора родителя, super вызывается неявно.

2 голосов
/ 06 января 2009

Как вы говорите, конструктор C вызывает конструктор B, который вызывает конструктор A. Вы можете вызывать любые методы «A» для объекта C, а объект C может видеть непубличные поля в A.

Даже если вы переопределите метод A "foo" в C, вы можете получить версию A с помощью "super.foo ()", предполагая, что B также не переопределяет ее.

1 голос
/ 06 января 2009

Насколько C знает, все, что не перезаписано в C, содержится в B, даже если под классом A находится реализация, где может быть реализация.

public class A {
   public A() {
   }

   public void aMethod() {
   }
}

public class B extends A {
   public B() {
     super();
   }
}

public class C extends B {
   public C() {
     super();
   }

   public void doWork() {
     super.aMethod();
   }
}

Таким образом, в этом случае A обрабатывает реализацию aMethod (), хотя вызов super () в конструкторе C вызывает непосредственно конструктор B, а не A.

...