Почему конструкторы не наследуются
От: eiNtiel  
Дата: 11.09.07 01:32
Оценка:
сабж
Re: Почему конструкторы не наследуются
От: shumer  
Дата: 11.09.07 04:07
Оценка:
"Конструкторы не относятся к категории методов и не наследуются". Арнольд, Гослинг, Холмс.
Re: Почему конструкторы не наследуются
От: fplab Россия http://fplab.h10.ru http://fplab.blogspot.com/
Дата: 11.09.07 04:31
Оценка:
Здравствуйте, eiNtiel, Вы писали:

N>сабж


А в каких случаях это могло бы быть полезным, что-то не придумаю подходящего примера ?
Наследуйте класс, вызывайте конструктор родителя и вот оно — счастье
Приходиться заниматься гадостью — зарабатывать на жизнь честным трудом (Б.Шоу)
Re[2]: Почему конструкторы не наследуются
От: eiNtiel  
Дата: 11.09.07 04:53
Оценка:
Здравствуйте, fplab, Вы писали:

F>А в каких случаях это могло бы быть полезным, что-то не придумаю подходящего примера ?

F>Наследуйте класс, вызывайте конструктор родителя и вот оно — счастье

Напрмер (псевдокод):
class A {
    A(HttpServletRequest req) {
        a = req.getA();
        b = req.getB();
        c = req.getC();
    }

    String a;
    String b;
    String c;

    ...
}

class B1 extends A {
    final String s = "Select " + a + ", " + b + " from table1";
    ...
}

class B2 extends A {
    final String s = "Select " + a + "from table2 where field = " + c;
    ...
}


Имеется ввиду следующее — конструктор нужен общий для всех наследуемых классов. Добавлять в производных классах туда впринципе нечего. В конструктор передается объект(ы) на основании которого выставляются значения полей базового класса. Поля производного класса хочется проинициализировать на основании значений полей базового
Re[2]: Почему конструкторы не наследуются
От: eiNtiel  
Дата: 11.09.07 04:54
Оценка:
Здравствуйте, shumer, Вы писали:

S>"Конструкторы не относятся к категории методов и не наследуются". Арнольд, Гослинг, Холмс.


Вопрос "почему" не раскрыт
Re[3]: Почему конструкторы не наследуются
От: shumer  
Дата: 11.09.07 04:59
Оценка:
Здравствуйте, eiNtiel, Вы писали:

N>Здравствуйте, shumer, Вы писали:


S>>"Конструкторы не относятся к категории методов и не наследуются". Арнольд, Гослинг, Холмс.


N>Вопрос "почему" не раскрыт


Почему же. Наследуются поля (данные) и методы (функции). Конструкторы не относятся ни к тем ни к другим, поэтому они не наследуются.
Re[4]: Почему конструкторы не наследуются
От: eiNtiel  
Дата: 11.09.07 05:02
Оценка:
Здравствуйте, shumer, Вы писали:

S>Почему же. Наследуются поля (данные) и методы (функции). Конструкторы не относятся ни к тем ни к другим, поэтому они не наследуются.


Скажем так, они относятся к категории конструкторов, интересует почему эта категория исключена из наследования
Re[5]: Почему конструкторы не наследуются
От: toad  
Дата: 11.09.07 05:34
Оценка:
Здравствуйте, eiNtiel, Вы писали:

N>Здравствуйте, shumer, Вы писали:


S>>Почему же. Наследуются поля (данные) и методы (функции). Конструкторы не относятся ни к тем ни к другим, поэтому они не наследуются.


N>Скажем так, они относятся к категории конструкторов, интересует почему эта категория исключена из наследования


А что, Вас убивает написать в потомке конструктор с тем же набором параметров, что и у предка, и вызвать в нём
 super(param1, param2, ... ets.)
?

Приведу Вам контр пример. Вот если бы конструкторы наследовались, то есть в любом классе потомке были бы все конструкторы с параметрами как у предка, то
1) Имели бы большой гемморой со скрытием конструктора (например в синглетонах)
2) Любой класс имел бы конструктор без параметров, т.к. он наследуется от класса Object
Re[3]: Почему конструкторы не наследуются
От: rsn81 Россия http://rsn81.wordpress.com
Дата: 11.09.07 05:43
Оценка:
Здравствуйте, eiNtiel, Вы писали:

N>Имеется ввиду следующее — конструктор нужен общий для всех наследуемых классов. Добавлять в производных классах туда впринципе нечего. В конструктор передается объект(ы) на основании которого выставляются значения полей базового класса.

  1. Конструкторы не наследуются подклассами.
    PS Кстати, забавно в этом отношении, что нет запрета на создание одноименного с названием класса внутреннего метода, который, разумеется, наследуется. Это порой вводит в относительно продолжительный ступор, пока не заметишь возвращаемый тип метода, которого у конструктора быть не может.
  2. Но при вызове конструктора (любого!) неявно вызываются последовательно по цепочке все конструкторы по умолчанию (без параметров!) его суперклассов: первым будет вызван конструктор Object и т.д. Каждый конструктор выполняется только после завершения родительского конструктора, при этом завершение конструктора класса означает инициализацию всех полей экземпляра этого класса.
  3. Абстрактный класс без конструктора по умолчанию, но с частным конструктором (имеющим параметры) налагает жесткое ограничение на классы-наследники: первой инструкцией конструктора класса наследника должен быть вызов родительского конструктора. Думаю, это ваш вариант: сделайте класс A абстрактным.

N>Поля производного класса хочется проинициализировать на основании значений полей базового

А что собственно мешает?
Re[5]: Почему конструкторы не наследуются
От: rsn81 Россия http://rsn81.wordpress.com
Дата: 11.09.07 05:58
Оценка:
Здравствуйте, eiNtiel, Вы писали:

N>Скажем так, они относятся к категории конструкторов, интересует почему эта категория исключена из наследования

Потому что термин "наследование" применим только к методам (ну и полям) класса, а конструктор != методу (и тем паче полю). Прочтите статью: Понятие конструктора. Чем отличается конструктор от метода.
Re[6]: Почему конструкторы не наследуются
От: eiNtiel  
Дата: 11.09.07 08:03
Оценка:
Здравствуйте, toad, Вы писали:

T>А что, Вас убивает написать в потомке конструктор с тем же набором параметров, что и у предка, и вызвать в нём
 super(param1, param2, ... ets.)
?


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

T>Приведу Вам контр пример. Вот если бы конструкторы наследовались, то есть в любом классе потомке были бы все конструкторы с параметрами как у предка, то

T>1) Имели бы большой гемморой со скрытием конструктора (например в синглетонах)
T>2) Любой класс имел бы конструктор без параметров, т.к. он наследуется от класса Object

Сдесь похоже Вы правы.
Re: Почему конструкторы не наследуются
От: LeonidV Ниоткуда http://vygovskiy.com
Дата: 11.09.07 08:04
Оценка: 18 (5) +2
Далее ПМСМ.
Конструкторы не наследуются, чтобы всегда гарантировать клиенту базового класса его контракт. Главное — гарантия, что все поля будут корректно инициализированы. Для предоставления этой гарантии помимо запрета на наследование конструкторов существуют еще ряд механизмов. Например, в любом конструкторе обязательно осуществляется вызов конструктора предка, причем обязательно в первую очередь.
На самом деле существует лазейка, которую разработчик класса может опустить и допустить ситуацию некорректной инициализации полей в потомке. Это применение не final методов для инициализации полей класса. В частности, это может быть метод установки (set). Как следствие, делать это категорически не рекомендуется.

Это было раз. Два, наследование конструкторов также может помешать создания хорошего контракта потомка. Например, рассмотрим ситуацию расширения полей предка в потомке еще одним полем.

class Base {
  private int x,y;
  Base(int x, int y) {
   this.x = x;
   this.y = y;
  }
class Child extend Base {
  private z;
  Child(int x, int y, int z) {
    super(x,y); 
    z = z;
  }
}

Наследование конструктора позволит сделать следующее:

Child c = new Child(1,2); // Используем конструктор класса Base;

и оставить поле z не проинициализированным.
http://jvmmemory.com — простой способ настройки JVM
Re[4]: Почему конструкторы не наследуются
От: eiNtiel  
Дата: 11.09.07 08:23
Оценка:
Здравствуйте, rsn81, Вы писали:

R>
  • Абстрактный класс без конструктора по умолчанию, но с частным конструктором (имеющим параметры) налагает жесткое ограничение на классы-наследники: первой инструкцией конструктора класса наследника должен быть вызов родительского конструктора. Думаю, это ваш вариант: сделайте класс A абстрактным.

    N>>Поля производного класса хочется проинициализировать на основании значений полей базового

    R>А что собственно мешает?

    Мешает отсутствие наследования конструкторов с которого все и начиналось. Либо дублирование кода в каждом потомке B(Object o) { super(O); }. ЛИбо просто использовать вместо конструктора метод, который прекрасно отнаследуется, но такая запись уже конечно не пройдет:

    class A {
        A() {
        }
    
        process(HttpServletRequest req) {
            a = req.getA();
            b = req.getB();
            c = req.getC();
        }
    
        String a;
        String b;
        String c;
    
        ...
    }
    
    class B1 extends A {
        final String s = "Select " + a + ", " + b + " from table1"; //Придется избавиться
        String s;
        ...
        [в одном из методов]  s = "Select " + a + ", " + b + " from table1";
    }
    
    class B2 extends A {
        final String s = "Select " + a + "from table2 where field = " + c;
        ...
    }


    И использование соответственно:
    A a = new B1();
    a.process(request);
  • Re[6]: Почему конструкторы не наследуются
    От: eiNtiel  
    Дата: 11.09.07 08:27
    Оценка:
    Здравствуйте, rsn81, Вы писали:

    R>Потому что термин "наследование" применим только к методам (ну и полям) класса, а конструктор != методу (и тем паче полю). Прочтите статью: Понятие конструктора. Чем отличается конструктор от метода.


    Ну опять 25 К счастью я знаю что такое конструктор. Толи я вопросы неправильно задаю толи... Вот это: "Любой класс имел бы конструктор без параметров, т.к. он наследуется от класса Object" аргумет. А то что конструктор != методу не объясняет причины.
    Re[6]: Почему конструкторы не наследуются
    От: rsn81 Россия http://rsn81.wordpress.com
    Дата: 11.09.07 08:38
    Оценка:
    Здравствуйте, toad, Вы писали:

    T>2) Любой класс имел бы конструктор без параметров, т.к. он наследуется от класса Object

    Скажем, если вы не зададите частный конструктор, то компилятор сгенерирует его в байт-коде за вас, но это, конечно, вовсе не наследование.
    Re[2]: Почему конструкторы не наследуются
    От: rsn81 Россия http://rsn81.wordpress.com
    Дата: 11.09.07 08:38
    Оценка: 1 (1)
    Здравствуйте, LeonidV, Вы писали:

    LV>На самом деле существует лазейка, которую разработчик класса может опустить и допустить ситуацию некорректной инициализации полей в потомке. Это применение не final методов для инициализации полей класса. В частности, это может быть метод установки (set). Как следствие, делать это категорически не рекомендуется.

    Добавлю, безопасность инициализации можно нарушить, если потерять указатель this, то есть опубликовать его в конструкторе: к примеру, подписаться на оповещение, передав издателю ссылку this, или сделать тоже самое с помощью создания в конструкторе анонимного подписчика — последствия аналогичные.
    Re[2]: Почему конструкторы не наследуются
    От: eiNtiel  
    Дата: 11.09.07 08:39
    Оценка:
    Здравствуйте, LeonidV, Вы писали:

    Согласен, все верно. Это у меня просто нестандартная ситуация когда в потомках нечего инициализировать. Вобщем понял, никуда от них не деться и это правильно )
    Re[3]: Почему конструкторы не наследуются
    От: C0s Россия  
    Дата: 11.09.07 08:45
    Оценка: 7 (2) +2 :))
    Здравствуйте, eiNtiel, Вы писали:

    N>Согласен, все верно. Это у меня просто нестандартная ситуация когда в потомках нечего инициализировать. Вобщем понял, никуда от них не деться и это правильно )


    с этого момента могла бы начаться, пожалуй, более интересная дискуссия на тему дизайна: откуда взялось столько потомков и проч...
    Re[4]: Почему конструкторы не наследуются
    От: eiNtiel  
    Дата: 11.09.07 08:53
    Оценка:
    Здравствуйте, C0s, Вы писали:

    C0s>с этого момента могла бы начаться, пожалуй, более интересная дискуссия на тему дизайна: откуда взялось столько потомков и проч...


    а "архитектура" такая родилась всвязи с этим
    Re: Почему конструкторы не наследуются
    От: dshe  
    Дата: 11.09.07 08:56
    Оценка: 1 (1)
    Здравствуйте, eiNtiel, Вы писали:

    Я скажу дикую вешь, но вообще-то конструкторы наследуются. Вы ведь можете вызвать из конструктора наследника конструктор базового класса (более того, просто обязаны это сделать). Но это я просто придираюсь к словам.

    В некоторых случаях, действительно, было бы удобно иметь в наследнике конструкторы с теми же самыми сигнатурами, что и конструкторов его базового класса. Причем так, чтобы это делалось автоматически (не надо было писать однообразный код руками). Это могло было бы выглядеть так
    public class Base() {
       public Base() {...}
       public Base(int i) {...}
       public Base(String s) {...}
       public Base(int i, String s) {...}
       ...
    }
    
    @GenerateConstructorsFromSuperclass
    public class Derived extends Base {
       ...
    }

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