Что на самом деле делает «extensions»?

В настоящее время я изучаю концепцию «абстракции класса» и «расширения» и задаюсь вопросом:
«Если я объявлю параметризованный конструктор внутри своего абстрактного класса, почему не будет работать расширение для другого класса, если я не объявлю себя конструктором с ключевым словом super, вызывающим параметры конструктора абстрактного класса?»

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

Это потому, что конструктор был параметризован или просто потому, что пустой конструктор не существует?

Вызывает ли ключевое слово расширяет что-то вроде этого?

Object myClass = new AbstractClass();

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

Object myClass = new AbstractClass(int foo,float boo);

И если это так, ключевое слово super по существу, если вы позволите мне термин, «помещает» параметры, указанные в скобках, «внутри» конструктора?

Если это не так, что я получаю неправильно? Как работает фактически?

Если ваш класс абстрактный, вы не можете создать его экземпляр с помощью ключевого слова new.

Michał Krzywański 21.06.2019 10:26

Вы в значительной степени поняли это. Хотя дело не столько в ключевое слово расширения, сколько в том, что ваш класс является подклассом другого класса. Ключевое слово extends используется в других ситуациях, кроме расширения класса, и в этом случае оно не делает всего того, что вы здесь обсуждали. Быть подклассом делает их.

kumesana 21.06.2019 10:26

Хорошо, я понимаю! большое спасибо! Итак, с расширениями я говорю моему подклассу наследовать атрибуты, конструкторы и методы абстрактного класса?

Matteo Perini 21.06.2019 10:33

Мне кажется, это хороший способ думать об этом. С несколько иной точки зрения вы можете думать об этом так: когда вы объявляете класс с одним конструктором, который принимает один или несколько параметров, вы «говорите» компилятору, что эти параметры необходимы для существования любого экземпляра класса. Foo. Поскольку экземпляр класса, который расширяет Foo, по сути, также является экземпляром Foo, то любые экземпляры расширяющего класса также должны требовать одни и те же параметры, хотя они могут быть предоставлены расширяющим классом, а не обязательно тем, кто создает этот объект.

DaveyDaveDave 21.06.2019 10:34

Я не понимаю вопрос Does the extends keyword call something along the lines of this? с примером Object myClass = new AbstractClass();. Не могли бы вы рассказать немного больше здесь?

lealceldeiro 21.06.2019 10:35

@lealceldeiro я имел в виду, когда делал это public class myClass extends AbstractClass это в основном делает это Object myClass = new AbstractClass();

Matteo Perini 21.06.2019 10:54
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
1
6
1 417
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

При инициализации объекта всегда будет вызываться конструктор. Даже если вы не определите один конструктор, будет конструктор по умолчанию без каких-либо параметров. Поэтому, если вы определяете конструктор в абстрактном классе, вы должны вызывать этот конструктор с помощью super().

Если вы не определяете никаких конструкторов, то он будет неявно вызываться как конструктор по умолчанию.

"If I declare a parametrized constructor inside my abstract class why won't extension on another class work unless I declare myself the constructor with the super keyword invoking the parameters of the abstract class's constructor?"

Потому что суперкласс говорит, что он ДОЛЖЕН быть конструктором, использующим этот объявленный конструктор, и другого пути нет. Это относится к каждому расширяющемуся классу - должен быть вызван требуемый конструктор.

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

public class A{
   //no default no-arg ctor here
   public A(String name){
       ....
   }

}

public class B{
  //default no-arg ctor will be created
}

так тогда

  B b=new B();
    A a=new A(); //// INVALID!
    A a=new A("foobar"); // yeah that is it

То же самое применимо, когда вы расширяете классы. Чтобы создать дочерний экземпляр, вы должны сначала «внутренне создать родительский экземпляр», вызвав super.constructor. Поскольку конструктора по умолчанию нет, необходимо использовать ЛЮБОЙ явно объявленный суперконструктор.

Ответ принят как подходящий

Вы должны думать о ключевом слове extends в этом контексте просто как о том, что класс является подклассом другого класса и ничего больше не делает. И что существуют правила, определяющие, как должны работать подклассы и суперклассы.

Когда вы создаете подкласс, вы должны сначала создать его суперкласс. Например, чтобы создать Bird, вы должны сначала создать Animal. Это имеет смысл, не так ли? Чтобы продемонстрировать это в коде:

class Animal {
    public Animal() {
        System.out.println("Animal");
    }
}

class Bird extends Animal {
    public Bird() {
        System.out.println("Bird");
    }
}

Выполнение new Bird() сначала напечатает Animal, а затем Bird, потому что сначала вызывается конструктор Animal, а затем конструктор Bird. Так что на самом деле конструктор Bird неявно вызывает конструктор суперкласса. Это можно записать как:

public Bird() {
    super();
    System.out.println("Bird");
}

Что произойдет, если суперкласс не имеет конструктора без параметров? Допустим, конструктор Animal теперь принимает String name в качестве аргумента. Вам все еще нужно сначала вызвать конструктор суперкласса, но super() не будет работать, потому что super() нужен строковый параметр!

Поэтому компилятор выдает вам ошибку. Это можно исправить, вызвав super() явный с параметром.

If I declare a parametrized constructor inside my abstract class why won't extension on another class work unless I declare myself the constructor with the super keyword invoking the parameters of the abstract class's constructor?

В AbstractClass нет конструктора по умолчанию, поскольку вы определяете параметризованный конструктор. Если вы не определяете конструктор самостоятельно, неявно создается конструктор по умолчанию без аргументов. Вы можете добавить такой вручную сейчас или вам нужно использовать доступный конструктор Только (который параметризован) с super().


Пример вашего кода с определением конструктора без аргументов:

class AbstractClass {
    AbstractClass() {} // added manually since not created implicitly
    AbstractClass(int foo, float boo) {}
}
class RealClass extends AbstractClass {
    RealClass() { } // calls super() implicitly
}
AbstractClass myClass = new RealClass();

Пример вашего кода с вызовом super() с аргументами:

class RealClass extends AbstractClass {
    RealClass() {
        super(1, 2);
    }
}
class AbstractClass {
    AbstractClass(int foo, float boo) {}
}
AbstractClass myClass = new RealClass();

Другие вопросы по теме