Можем ли мы иметь тип возвращаемого значения для конструктора в Java? - PullRequest
10 голосов
/ 17 августа 2010

Следующий код выдает ошибку компиляции:

class parent {
  parent(int a){}
}

class child extends parent{}

Ошибка:

Main.java:6: cannot find symbol
symbol  : constructor parent()
location: class parent
class child extends parent{}
^
1 error

Я пытался делать разные вещи и обнаружил, что добавление типа возврата к родительскому конструктору избавило от ошибки !!!

class parent {
  int parent(int a){}
}

class child extends parent{}

Я читал, что конструкторы не должны иметь тип возвращаемого значения, что явно не всегда правильно. Итак, мой вопрос, когда мы должны иметь тип возвращаемого значения для конструктора?

Ответы [ 11 ]

29 голосов
/ 17 августа 2010

В случае 1 дочерний класс не имеет никакого конструктора, поэтому компилятор добавляет конструктор по умолчанию для вас, а также добавляет вызов конструктора суперкласса.Таким образом, ваш дочерний класс выглядит следующим образом:

class child extends parent {
 child() {
  super();
 }
}

вызов super() ищет конструктор с нулевым аргументом в базовом классе, поскольку такого конструктора нет, вы получите ошибку.

В случае 2 родительский родительский класс не имеет конструктора

int parent(int x) {} является , а не конструктором, поскольку имеет тип возвращаемого значения.Это просто метод, который имеет имя класса.Дочерний класс также не имеет конструктора.Таким образом, компилятор добавляет конструктор по умолчанию для дочернего и родительского элемента, а также добавляет вызов конструктора суперкласса:

class parent {
 parent() {
  super(); // calls Object class ctor.
 }
  int parent(int x) {} // not a ctor.
}

class child extends parent {
 child() {
  super();
 }
}
18 голосов
/ 17 августа 2010

В конструкторе, не имеющем тип возврата

Конструктор не должен иметь тип возвращаемого значения. По определению, если метод имеет тип возвращаемого значения, это не конструктор.

JLS 8.8 Объявления конструктора

Конструктор используется при создании объекта, который является экземпляром класса. [Имя должно соответствовать имени класса, но] во всех других отношениях объявление конструктора выглядит так же, как объявление метода, у которого нет типа результата.


По умолчанию конструкторы

Следующий фрагмент кода выдает ошибку компиляции:

class Parent {
   Parent(int a){}
}

class Child extends Parent{

   // DOES NOT COMPILE!!
   // Implicit super constructor parent() is undefined for default constructor.
   // Must define an explicit constructor

}

Причина не в типе возвращаемого значения в конструкторе, а в том, что поскольку вы не предоставили конструктор ANY для Child, автоматически создается конструктор default компилятором. Однако этот конструктор по умолчанию пытается вызвать конструктор по умолчанию суперкласса Parent, который NOT имеет конструктор по умолчанию. ЭТО источник ошибки компиляции.

Вот спецификация для конструктора по умолчанию:

JLS 8.8.9 Конструктор по умолчанию

Если класс не содержит объявлений конструктора, автоматически предоставляется конструктор по умолчанию , который не принимает параметров:

  • Если объявленный класс является первичным классом Object, то конструктор по умолчанию имеет пустое тело.
  • В противном случае конструктор по умолчанию не принимает параметров и просто вызывает конструктор суперкласса без аргументов.

Ниже приведено простое исправление:

class Parent {
   Parent(int a){}
}

class Child extends Parent{

   // compiles fine!
   Child() {
      super(42);
   }

}

О методах с тем же именем, что и у конструктора

Следующий фрагмент DOES compile:

// COMPILES FINE!!

class Parent  {

   // method has same name as class, but not a constructor
   int Parent(int a) {
      System.out.println("Yipppee!!!");
      return 42;
   }

   // no explicit constructor, so default constructor is provided
}

class Child extends Parent {

   // no explicit constructor, so default constructor is provided

}

На самом деле в приведенном фрагменте нет явного конструктора. У вас есть обычный метод с тем же именем, что и у класса. Это разрешено, но не рекомендуется:

JLS 8.4 Объявления методов

A class может объявить метод с тем же именем, что и class или полем, членом class или членом interface класса, , но это не рекомендуется как вопрос стиля .

Вы обнаружите, что если вы создадите new Parent() или new Child(), "Yipppee!!!" будет НЕ выводиться на стандартный вывод. Метод не вызывается при создании, поскольку он не является конструктором.

4 голосов
/ 17 августа 2010
  • когда вы расширяете класс, у которого нет конструктора по умолчанию, вы должны предоставить конструктор, который вызывает этот суперконструктор - вот почему ошибка компиляции:

Неявный супер-конструктор parent () не определен для конструктора по умолчанию. Должен определить явный конструктор

  • когда вы добавляете тип возвращаемого значения, он больше не является конструктором, это метод, и вышеописанное не применяется

В будущем сначала прочитайте сообщения об ошибках и попытайтесь выяснить (или найти), что это означает.

2 голосов
/ 17 августа 2010

конструкторы не имеют типа возврата

2 голосов
/ 17 августа 2010

Конструкторы не имеют тип возврата.Конструкторы вызываются для создания экземпляра типа.По сути, то, что «возвращается» из конструктора, является экземпляром этого типа, готовым к использованию.

1 голос
/ 17 августа 2010

Уже ответил codaddict, но два комментария.По соглашению Java-кода классы должны начинаться с верхнего регистра (также полезно добавить модификатор).Если у вас есть ошибка компиляции, то укажите ее, все без исключения было ясно:

1 голос
/ 17 августа 2010

Технически, вы не добавили возвращаемый тип в конструктор, но изменили конструктор на метод, который, как оказалось, имел то же имя, что и класс. То, что вы должны были сделать, это позвонить super(int), таким образом:

class parent 
{
parent(int a){}
}

class child extends parent{ child(int a){ super(a); } }

Ваш код для child неявно пытается сделать это:

class child extends parent{ child(){ super(); } }

То есть он пытается вызвать конструктор с нулевым аргументом в parent, что явно невозможно сделать, так как он имеет только один конструктор, который принимает аргумент int.

1 голос
/ 17 августа 2010

попробуйте изменить его на:

class parent 
{
parent(int a){}
}

class child extends parent
{
  child(int a){
    super(a);
  }
}
0 голосов
/ 26 августа 2014

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

0 голосов
/ 17 августа 2010

1) Лучше всего начинать занятия с заглавной буквы, а методы с заглавной буквы.

2) Если вы не создаете конструктор для класса, он имеет пустой конструктор по умолчанию.

3) При наследовании от класса вам необходимо переопределить хотя бы один из его конструкторов, а если вы не укажете их, вы автоматически наследуете пустой конструктор.

Код, который вы отправили, работал бы, если бы у child был конструктор, вызывающий super(int i), если у родительского класса не было конструктора (тогда у него был бы пустой конструктор по умолчанию) или если родительский класс специально реализовал пустой конструктор.

Это будет работать.

public class Parent {
    public Parent(int i) { }
    public Parent() { }
}

public class Child {
}

Пустой дочерний класс ведет себя так, как если бы он был написан так:

public class Child {
    public Child() {
        super();
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...