Можем ли мы иметь тип возврата для конструктора в Java?

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

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{}

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

10
задан codaddict 18 August 2010 в 03:15
поделиться

10 ответов

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

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

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

}

Причина не в возвращаемом типе конструктора, а в том, что вы не предоставили ЛЮБОЙ конструктор для Дочерний , конструктор по умолчанию автоматически создается для вас компилятором. Однако этот конструктор по умолчанию пытается вызвать конструктор по умолчанию суперкласса Parent , который НЕ имеет конструктор по умолчанию. ЭТО источник ошибки компиляции.

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

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

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

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

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

class Parent {
   Parent(int a){}
}

class Child extends Parent{

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

}

Для методов, имеющих то же имя, что и конструктор

Следующий фрагмент ДЕЛАЕТ компиляцию:

// 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 Объявления методов

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

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

18
ответ дан 3 December 2019 в 13:17
поделиться

В случае 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();
 }
}
29
ответ дан 3 December 2019 в 13:17
поделиться
  • когда вы расширяете класс, у которого нет конструктора по умолчанию, вы должны предоставить конструктор, который вызывает этот суперконструктор - вот почему возникает ошибка компиляции, которая:

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

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

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

4
ответ дан 3 December 2019 в 13:17
поделиться

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

2
ответ дан 3 December 2019 в 13:17
поделиться

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

class parent 
{
parent(int a){}
}

class child extends parent
{
  child(int a){
    super(a);
  }
}
1
ответ дан 3 December 2019 в 13:17
поделиться

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

1
ответ дан 3 December 2019 в 13:17
поделиться

Все, что вы сделали, добавив int, - это превратили «конструктор» в метод с видимостью по умолчанию, а затем, поскольку вы не указали конструктор, он просто добавит конструктор по умолчанию для вас во время компиляции.

Если вы хотите, чтобы это скомпилировалось, вам нужно будет указать конструктор по умолчанию, который и ищет дочерний класс, например:

  class parent 
    {
      parent(int a){}

      parent(){}
    }

class child extends parent{}
0
ответ дан 3 December 2019 в 13:17
поделиться

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

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

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

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

Это сработает.

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

public class Child {
}

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

public class Child {
    public Child() {
        super();
    }
}
0
ответ дан 3 December 2019 в 13:17
поделиться

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

2
ответ дан 3 December 2019 в 13:17
поделиться

Технически, вы не добавляли возвращаемый тип в конструктор, а изменили конструктор на метод, который случайно оказался с тем же именем, что и класс. Вам следовало вызвать 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
ответ дан 3 December 2019 в 13:17
поделиться
Другие вопросы по тегам:

Похожие вопросы: