Что такое super java
Перейти к содержимому

Что такое super java

  • автор:

Для чего нужно ключевое слово super?

Как и многие другие ключевые слова, super имеет несколько разных значений в зависимости от контекста:

1. Задать нижнюю границу generic-типа: Consumer
2. Обратиться к члену класса-родителя, который перекрыт (shadowed) членами наследника или локальными переменными: int foo = super.foo
3. Вызвать в конструкторе конструктор родителя: SubClass() < super("subclass param"); >
4. В случае неопределенности, уточнить родительский тип (на картинке)

Ключевое слово super

Ключевое слово super в Java используется тогда, когда подклассу требуется сослаться на его непосредственный супер класс.

У ключевого слова super имеются две общие формы:

    Для вызова конструктора супер класса:

super(списокАргументов);​
suреr.member;​

2. Вызов конструкторов супер класса с помощью ключевого слова super

Если в иерархии классов требуется передать параметры конструктору супер класса, то все подклассы должны передавать эти параметры вверх по иерархии. То есть из конструктора подкласса надо вызвать конструктор супер класса с помощью super() . Когда метод super() вызывается из подкласса, вызывается конструктор его непосредственного супер класса. Это справедливо даже для многоуровневой иерархии.

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

В этом примере из конструктора класса HeavyBox1 вызываем конструктора класса Box6 c помощью super() , тем самым передавая необходимые значения:

public class Box6 < double width; double height; double depth; Box6(double w, double h, double d) < width = w; height = h; depth = d; >public Box6() < >>
public class HeavyBox1 extends Box6 < int weight; public HeavyBox1(int width, int height, int depth, int weight) < super(width, height, depth); this.weight = weight; >public HeavyBox1() < this.weight = -1; >>

Если в конструкторе наследника нет явного вызова super() , как например во втором конструкторе класса HeavyBox1 , JVM сама его подставляет первой строкой:

public HeavyBox1()

Из этого следует, что супер класс должен иметь конструктор без параметров, иначе возникнет ошибка компиляции.

3. Обращения к члену супер класса с помощью ключевого слова super

С помощью ключевого слова super можно обратиться к члену супер класса из класса наследника. Чаще всего это можно сделать не используя super , но в этом примере рассмотрим случаи, когда без него не обойтись.

В классе С объявлена переменная i типа int . В его наследнике классе D , тоже объявлена переменная i , но типа String . (Сразу же предупредим — на практике не стоит так делать! Пример приводится с целью иллюстрирования применение ключевого слова super с переменными.) Из класса D мы можем напрямую обратиться только к переменной String i , которая перекрывает область видимости переменной int i . Для обращения же к int i , необходимо использовать слово super .

Похожая ситуация и с методами. В обоих классах определен метод print() . Если мы хотим из класса D вызвать метод print() класса С , используем слово super super.print() .

public class C < public int i; public void print() < System.out.println("C.i = " + i); >> public class D extends C < public String i; public D(String a, int b) < i = a; super.i = b; >public void print() < System.out.println("D.i = " + i); super.print(); >> public class UseSuper < public static void main(String[] args) < D d = new D("someString", 2); d.print(); System.out.println(d.i); >>

Вывод на консоль:

D.i = someString C.i = 2 someString

Что такое super java

Если Ваш метод переопределяет один из методов своего суперкласса, можно вызвать переопределенный метод с помощью ключевого слова super . Можно также использовать super обратиться к скрытому полю (хотя сокрытию полей обескураживают). Рассмотрите этот class, Superclass :

public class Superclass < public void printMethod() < System.out.println("Printed in Superclass."); >>

Вот подкласс, вызванный Subclass , это переопределяет printMethod() :

public class Subclass extends Superclass < // overrides printMethod in Superclass public void printMethod() < super.printMethod(); System.out.println("Printed in Subclass"); >public static void main(String[] args) < Subclass s = new Subclass(); s.printMethod(); >>

В пределах Subclass , простое имя printMethod() обращается к тому, объявленному в Subclass , который переопределяет тот в Superclass . Так, чтобы обратиться к printMethod() наследованный от Superclass , Subclass должен использовать полностью определенное имя, используя super как показано. Компиляция и выполнение Subclass печатает следующее:

Printed in Superclass. Printed in Subclass

Конструкторы подкласса

Следующий пример иллюстрирует, как использовать super ключевое слово, чтобы вызвать конструктора суперкласса. Вспомните из Bicycle пример это MountainBike подкласс Bicycle . Вот MountainBike конструктор (подкласса), который вызывает конструктора суперкласса и затем добавляет собственный код инициализации:

public MountainBike(int startHeight, int startCadence, int startSpeed, int startGear)

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

Синтаксис для того, чтобы вызвать конструктора суперкласса

super();
super(parameter list);

С super() , суперкласс конструктор без параметров вызывают. С super(parameter list) , конструктора суперкласса с соответствующим списком параметров вызывают.

Отметьте: Если конструктор явно не вызывает конструктора суперкласса, компилятор Java автоматически вставляет звонок в конструктора без параметров суперкласса. Если у class высшего качества не будет конструктора без параметров, то Вы получите ошибку времени компиляции. Object действительно имеет такого конструктора, так если Object единственный суперкласс, нет никакой проблемы.

Если конструктор подкласса вызывает конструктора его суперкласса, или явно или неявно, Вы могли бы думать, что будет целая цепочка вызванных конструкторов, полностью назад конструктору Object . Фактически, дело обстоит так. Это вызывают конструктором, объединяющим в цепочку, и Вы должны знать об этом, когда есть длинная линия спуска class.

Ваше использование этой страницы и всего материала на страницах под «Учебным баннером» Java подвергается этим официальным уведомлениям.

Авторское право © 1995, 2012 Oracle и/или его филиалы. Все права защищены.

Ключевое слово super, оператор instanceof

На предыдущем занятии мы с вами рассмотрели основу механизма наследования. Здесь затронем некоторые важные нюансы этого процесса и начнем с рассмотрения ключевого слова super.

Ключевое слово super

Часто в базовых классах имеются несколько конструкторов. Как в этом случае узнать, какой из конструкторов будет вызван при создании объекта дочернего класса? Например, объявим два класса:

class Properties { int width, color; Properties() { System.out.println("Конструктор Properties()"); } Properties(int width, int color) { this.width = width; this.color = color; System.out.println("Конструктор Properties(width, color)"); } } class Line extends Properties { double x1, y1; double x2, y2; Line() { System.out.println("Конструктор Line()"); } }

Здесь в базовом классе Properties два конструктора. Если теперь выполнить создание объекта дочернего класса Line:

Line line = new Line();

то в консоли увидим строчки:

Конструктор Properties()
Конструктор Line()

Это говорит о том, что при создании объекта базового класса, вызывается или конструктор без аргументов, или конструктор по умолчанию. Причем, конструктор по умолчанию будет существовать, только если в классе не объявлены никакие другие конструкторы. То есть, если конструктор Properties() закомментировать и оставить только второй, то объект дочернего класса Line не будет создан, возникнет ошибка, т.к. отсутствует конструктор без аргументов. А вот если в комментарии поставить и второй конструктор, то все заработает благодаря появлению конструктора по умолчанию.

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

class Line extends Properties { double x1, y1; double x2, y2; Line() { super(0, 0); System.out.println("Конструктор Line()"); } }

Здесь в конструкторе Line первой строчкой идет вызов конструктора базового класса с двумя аргументами. Обратите внимание, вызывать конструктор базового класса следует сразу же в первой строчке, т.к. сначала должен быть создан объект базового класса, а затем уже, объект дочернего класса.

При запуске программы увидим две строчки:

Конструктор Properties(width, color)
Конструктор Line()

Причем, если у нас цепочка из нескольких классов, унаследованных друг от друга, то super будет ссылаться на ближайший базовый класс:

Ключевое слово super в роли ссылки

После создания объекта базового класса, ключевое слово super можно использовать как ссылку на этот объект. Например, определим в базовом классе целочисленное поле id со значением 1:

int id = 1;

и точно такое же поле в дочернем классе, но со значением 2:

int id = 2;

Как теперь из дочернего класса обратиться к id базового класса? Да, это можно сделать через ссылку super:

class Line extends Properties { int id = 2; . void showId() { System.out.println("id = "+ id + ", super.id = " + super.id); } }

При вызове этого метода, в консоли увидим:

id = 2, super.id = 1

Также, если определить метод showId() в базовом классе:

class Properties { int id = 1; . void showId() { System.out.println("id = "+ id); } }

то мы можем к нему обратиться из дочернего через ссылку super:

class Line extends Properties { int id = 2; . void showId() { super.showId(); System.out.println("id = "+ id + ", super.id = " + super.id); } }

Вот так можно вызывать переопределенные поля и методы из объекта базового класса, используя ссылку super.

Оператор instanceof

В действительности в Java любой класс автоматически наследуется от предопределенного класса Object. То есть, иерархию наследования в нашем примере следовало бы изобразить вот так:

И объекты дочерних классов можно было бы создавать, используя ссылку типа Object:

Object g1 = new Line(); Object g2 = new Triangle(); Object g3 = new Properties();

При этом тип данных для ссылок g1, g2, g3 будет автоматически приведен к типу Object, т.к. это базовый суперкласс для всех этих объектов. Это, так называемое, восходящее преобразование (по-английски upcasting). Но мы можем выполнять и нисходящие преобразования: от ссылок на базовые классы к ссылкам на дочерние классы. Такое обратное преобразование типов автоматически уже не происходит и мы должны явно указать, какой тип дочернего класса нам нужен. Например, так:

Line l1 = (Line)g1; Line l2 = (Line)g2; // ошибка - это класс Triangle Properties p1 = (Properties)g3;

И смотрите, что может произойти. Когда мы пытаемся ссылку g2 привести к типу Line, то в процессе выполнения программы возникнет исключение (ошибка), что класс Triangle не может быть приведен к классу Line. И это логично, т.к. оба класса – самостоятельные дочерние, унаследованные от Properties. Нельзя один подменить другим. Но, хорошо, мы в этой простой программе знаем, что g2 – это ссылка на Triangle. А как быть в сложных проектах, когда имеется обобщенная ссылка и нам важно знать, какие дочерние классы включены в объект, на который ссылается g2? Для таких случаев существует оператор

который возвращает true, если имя дочернего класса содержится в объекте, по указанной ссылке. Например, прежде чем выполнять нисходящее преобразование типов, было бы правильно проверить, а содержится ли объект дочернего класса в объекте, к которому мы хотим привести тип данных:

Line l1 = null, l2 = null; if(g1 instanceof Line) l1 = (Line)g1; if(g2 instanceof Line) l2 = (Line)g2; // это класс Triangle Properties p1 = null; if(g3 instanceof Properties) p1 = (Properties)g3;

Теперь, при запуске программы у нас никаких ошибок не будет, т.к. проверка g2 instanceof Line будет ложной и преобразование не выполняется.

Путь кодера

  • displayPen() – для отображения данных по ручкам;
  • displayPencil() – для отображения данных по карандашам;
  • displayNotebook() – для отображения данных по тетрадям.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *