В чем разница между ключевыми словами this
и super
?
Оба используются для доступа к конструкторам класса справа? Может ли кто-нибудь из вас объяснить?
В чем разница между ключевыми словами this
и super
?
Оба используются для доступа к конструкторам класса справа? Может ли кто-нибудь из вас объяснить?
Давайте рассмотрим эту ситуацию
class Animal {
void eat() {
System.out.println("animal : eat");
}
}
class Dog extends Animal {
void eat() {
System.out.println("dog : eat");
}
void anotherEat() {
super.eat();
}
}
public class Test {
public static void main(String[] args) {
Animal a = new Animal();
a.eat();
Dog d = new Dog();
d.eat();
d.anotherEat();
}
}
Выход будет
animal : eat
dog : eat
animal : eat
В третьей строке печатается "животное: есть", потому что мы вызываем super.eat()
. Если бы мы назвали this.eat()
, он напечатал бы как "собака: есть".
super
используется для доступа к методам базового класса, а this
используется для доступа к методам текущего класса.
Расширение понятия, если вы пишете super()
, оно ссылается на конструктор базового класса, и если вы пишете this()
, он ссылается на конструктор самого класса, в котором вы пишете этот код.
this
- это ссылка на объект, набранный как текущий класс, а super
- ссылка на объект, введенный как его родительский класс.
В конструкторе this()
вызывает конструктор, определенный в текущем классе. super()
вызывает конструктор, определенный в родительском классе. Конструктор может быть определен в любом родительском классе, но он будет ссылаться на тот, который был переопределен ближе всего к текущему классу. Вызовы для других конструкторов таким образом могут выполняться только как первая строка в конструкторе.
Методы вызова работают одинаково. Вызов this.method()
вызывает метод, определенный в текущем классе, где super.method()
вызывает тот же метод, что и в родительском классе.
Из вашего вопроса, я полагаю, вы действительно спрашиваете об использовании this
и super
в цепочке конструкторов; например.
public class A extends B {
public A(...) {
this(...);
...
}
}
против
public class A extends B {
public A(...) {
super(...);
...
}
}
Разница проста:
Форма this
формирует цепочку к конструктору текущего класса; т.е. в классе A
.
Форма super
формирует цепочку к конструктору в непосредственном суперклассе; т.е. в классе B
.
this
относится к ссылке класса current. super
относится к родительскому текущего класса (который называется ключевым словом super
).
Выполняя this
, вы можете получить доступ к методам/атрибутам текущего класса (включая его собственные частные методы/атрибуты).
super
позволяет вам получить доступ к общедоступному/защищенному методу/атрибутам родительского (базового) класса. Вы не можете видеть родительский частный метод/атрибуты.
this
используется для доступа к методам и полям текущего объекта. По этой причине он не имеет смысла в статических методах, например.
super
позволяет получить доступ к нефизическим методам и полям в суперклассе и получить доступ к конструкторам только из конструкторов класса.
При написании кода вы, как правило, не хотите повторять себя. Если у вас есть класс, который может быть сконструирован с различным количеством параметров, общим решением, чтобы избежать повторения, является просто вызов другого конструктора со значениями по умолчанию в отсутствующих аргументах. Для этого есть только одно раздражающее ограничение - это должна быть первая строка объявленного конструктора. Пример:
MyClass()
{
this(default1, default2);
}
MyClass(arg1, arg2)
{
validate arguments, etc...
note that your validation logic is only written once now
}
Что касается конструктора super()
, опять же в отличие от super.method()
доступа, он должен быть первой строкой вашего конструктора. После этого он очень похож на конструкторы this()
, DRY (Do not Repeat Yourself), если класс, который вы продлеваете, имеет конструктор, который делает некоторые из того, что вы хотите, затем используйте его, а затем продолжайте строить свой объект, например:
YourClass extends MyClass
{
YourClass(arg1, arg2, arg3)
{
super(arg1, arg2) // calls MyClass(arg1, arg2)
validate and process arg3...
}
}
Дополнительная информация:
Даже если вы этого не видите, конструктор аргументов default по умолчанию всегда вызывает super()
. Пример:
MyClass()
{
}
эквивалентно
MyClass()
{
super();
}
Я вижу, что многие упомянули, используя ключевые слова this
и super
для методов и переменных - все хорошо. Просто помните, что конструкторы имеют уникальные ограничения на их использование, наиболее примечательным является то, что они должны быть самой первой инструкцией объявленного конструктора, и вы можете использовать только один.
это ключевое слово для вызова конструктора в том же классе (другой перегруженный конструктор)
синтаксис: этот (список args);//совместим с списком аргументов в другом конструкторе в том же классе
супер используется ключевое слово для вызова конструктора в суперклассе.
синтаксис: super (список args);//совместим с списком args в конструкторе суперкласса.
Пример:
public class Rect {
int x1, y1, x2, y2;
public Rect(int x1, int y1, int x2, int y2) // 1st constructor
{ ....//code to build a rectangle }
}
public Rect () { // 2nd constructor
this (0,0,width,height) // call 1st constructor (because it has **4 int args**), this is another way to build a rectangle
}
public class DrawableRect extends Rect {
public DrawableRect (int a1, int b1, int a2, int b2) {
super (a1,b1,a2,b2) // call super class constructor (Rect class)
}
}
1. использование ключевого слова SUPER.
Если ваш метод переопределяет один из его методов суперкласса, вы можете вызвать переопределенный метод с помощью ключевого слова super. Вы также можете использовать супер, чтобы ссылаться на скрытое поле (хотя скрывать поля не рекомендуется). Рассмотрим этот класс, Суперкласс:
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();
}
}
Внутри подкласса простое имя printMethod() относится к объявлению в подклассе, которое переопределяет значение в суперклассе. Итак, чтобы ссылаться на printMethod(), унаследованный от Superclass, Subclass должен использовать квалифицированное имя, используя super, как показано. Компиляция и выполнение подкласса печатает следующее:
Отпечатано в суперклассе. Отпечатано в подклассе.
2. использование ключевого слова THIS Используя это с полем
Наиболее распространенной причиной использования этого ключевого слова является то, что поле затеняется параметром метода или конструктора.
Например, класс Point был написан следующим образом:
public class Point {
public int x = 0;
public int y = 0;
//constructor
public Point(int a, int b) {
x = a;
y = b;
}
}
но это могло быть написано так:
public class Point {
public int x = 0;
public int y = 0;
//constructor
public Point(int x, int y) {
this.x = x;
this.y = y;
}
}
Каждый аргумент конструктора затеняет одно из полей объекта - внутри конструктора x есть локальная копия первого аргумента конструктора. Чтобы обратиться к полю Point x, конструктор должен использовать this.x.
Используя это с конструктором
Внутри конструктора вы также можете использовать это ключевое слово для вызова другого конструктора в том же классе. Это называется явным вызовом конструктора. Вот еще один класс Rectangle, с другой реализацией от той, что находится в разделе "Объекты".
public class Rectangle {
private int x, y;
private int width, height;
public Rectangle() {
this(0, 0, 0, 0);
}
public Rectangle(int width, int height) {
this(0, 0, width, height);
}
public Rectangle(int x, int y, int width, int height) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
}
}
Этот класс содержит набор конструкторов. Каждый конструктор инициализирует некоторые или все переменные элемента прямоугольника. Конструкторы предоставляют значение по умолчанию для любой переменной-члена, начальное значение которой не предоставляется аргументом. Например, конструктор без аргументов вызывает конструктор с четырьмя аргументами с четырьмя значениями 0, а конструктор с двумя аргументами вызывает конструктор с четырьмя аргументами с двумя значениями 0. Как и раньше, компилятор определяет, какой конструктор должен вызывать, исходя из числа и типа аргументов.
Если присутствует, вызов другого конструктора должен быть первой строкой в конструкторе.
Примечание:
Мы можем использовать super() и this() только в конструкторе не где-либо еще, попытка сделать это приведет к ошибке времени компиляции.
Мы должны сохранить либо super(), либо this() в качестве первой строки конструктор, но НЕ оба одновременно.
ПРИМЕЧАНИЕ.. Мы можем использовать оба из них в любом месте класса, кроме статических областей (статический блок или метод), любой попытка сделать это приведет к ошибке времени компиляции.
Это почти похоже на ситуацию, когда человек задал вопрос, что каждый видит только один возможный ответ. Тем не менее, человек называет каждый ответ не ответом, поэтому каждый пытается по-другому ответить на один и тот же ответ, поскольку есть только один способ ответить на него.
Итак, один человек начинает с A - это класс, а B - его подкласс. Следующий человек начинается с того, что C - класс, а B - его подкласс. Третий человек отвечает на него несколько иначе. A - класс, а B - продолжение A. Тогда четвертый говорит, что A является классом A, который расширяется по мере того, как B определен. Или Animal - это класс, а Dog - подкласс. Или нация - это класс, а Китай - особый случай нации.
Или еще лучше, Человек - класс, а Кларк Кент - подкласс Человека. Итак, Супермен... нет... это не работает с точки зрения Java....
Хорошо, это, по крайней мере, еще одна попытка придумать другое описание, которое никто не придумал, что может объяснить вещи по-другому. Arggghhhh.
Мне кажется, что все объяснения работали, кроме моего.