Java method override super

Overriding and Hiding Methods

An instance method in a subclass with the same signature (name, plus the number and the type of its parameters) and return type as an instance method in the superclass overrides the superclass’s method.

The ability of a subclass to override a method allows a class to inherit from a superclass whose behavior is «close enough» and then to modify behavior as needed. The overriding method has the same name, number and type of parameters, and return type as the method that it overrides. An overriding method can also return a subtype of the type returned by the overridden method. This subtype is called a covariant return type.

When overriding a method, you might want to use the @Override annotation that instructs the compiler that you intend to override a method in the superclass. If, for some reason, the compiler detects that the method does not exist in one of the superclasses, then it will generate an error. For more information on @Override , see Annotations .

Static Methods

If a subclass defines a static method with the same signature as a static method in the superclass, then the method in the subclass hides the one in the superclass.

Читайте также:  Java list string add all

The distinction between hiding a static method and overriding an instance method has important implications:

  • The version of the overridden instance method that gets invoked is the one in the subclass.
  • The version of the hidden static method that gets invoked depends on whether it is invoked from the superclass or the subclass.

Consider an example that contains two classes. The first is Animal , which contains one instance method and one static method:

public class Animal < public static void testClassMethod() < System.out.println("The static method in Animal"); >public void testInstanceMethod() < System.out.println("The instance method in Animal"); >>

The second class, a subclass of Animal , is called Cat :

public class Cat extends Animal < public static void testClassMethod() < System.out.println("The static method in Cat"); >public void testInstanceMethod() < System.out.println("The instance method in Cat"); >public static void main(String[] args) < Cat myCat = new Cat(); Animal myAnimal = myCat; Animal.testClassMethod(); myAnimal.testInstanceMethod(); >>

The Cat class overrides the instance method in Animal and hides the static method in Animal . The main method in this class creates an instance of Cat and invokes testClassMethod() on the class and testInstanceMethod() on the instance.

The output from this program is as follows:

The static method in Animal The instance method in Cat

As promised, the version of the hidden static method that gets invoked is the one in the superclass, and the version of the overridden instance method that gets invoked is the one in the subclass.

Interface Methods

Default methods and abstract methods in interfaces are inherited like instance methods. However, when the supertypes of a class or interface provide multiple default methods with the same signature, the Java compiler follows inheritance rules to resolve the name conflict. These rules are driven by the following two principles:

    Instance methods are preferred over interface default methods. Consider the following classes and interfaces:

public interface Mythical < default public String identifyMyself() < return "I am a mythical creature."; >>
public class Pegasus extends Horse implements Flyer, Mythical < public static void main(String. args) < Pegasus myApp = new Pegasus(); System.out.println(myApp.identifyMyself()); >>
public interface EggLayer extends Animal < default public String identifyMyself() < return "I am able to lay eggs."; >>

public interface FireBreather extends Animal

public class Dragon implements EggLayer, FireBreather < public static void main (String. args) < Dragon myApp = new Dragon(); System.out.println(myApp.identifyMyself()); >>

If two or more independently defined default methods conflict, or a default method conflicts with an abstract method, then the Java compiler produces a compiler error. You must explicitly override the supertype methods.

Consider the example about computer-controlled cars that can now fly. You have two interfaces ( OperateCar and FlyCar ) that provide default implementations for the same method, ( startEngine ):

public interface OperateCar < // . default public int startEngine(EncryptedKey key) < // Implementation >>

A class that implements both OperateCar and FlyCar must override the method startEngine . You could invoke any of the of the default implementations with the super keyword.

public class FlyingCar implements OperateCar, FlyCar < // . public int startEngine(EncryptedKey key) < FlyCar.super.startEngine(key); OperateCar.super.startEngine(key); >>

The name preceding super (in this example, FlyCar or OperateCar ) must refer to a direct superinterface that defines or inherits a default for the invoked method. This form of method invocation is not restricted to differentiating between multiple implemented interfaces that contain default methods with the same signature. You can use the super keyword to invoke a default method in both classes and interfaces.

Inherited instance methods from classes can override abstract interface methods. Consider the following interfaces and classes:

public class Mustang extends Horse implements Mammal < public static void main(String. args) < Mustang myApp = new Mustang(); System.out.println(myApp.identifyMyself()); >>

The method Mustang.identifyMyself returns the string I am a horse. The class Mustang inherits the method identifyMyself from the class Horse , which overrides the abstract method of the same name in the interface Mammal .

Note: Static methods in interfaces are never inherited.

Modifiers

The access specifier for an overriding method can allow more, but not less, access than the overridden method. For example, a protected instance method in the superclass can be made public, but not private, in the subclass.

You will get a compile-time error if you attempt to change an instance method in the superclass to a static method in the subclass, and vice versa.

Summary

The following table summarizes what happens when you define a method with the same signature as a method in a superclass.

Defining a Method with the Same Signature as a Superclass’s Method

Superclass Instance Method Superclass Static Method
Subclass Instance Method Overrides Generates a compile-time error
Subclass Static Method Generates a compile-time error Hides

Note: In a subclass, you can overload the methods inherited from the superclass. Such overloaded methods neither hide nor override the superclass instance methods—they are new methods, unique to the subclass.

Источник

Java Method Overriding

In the last tutorial, we learned about inheritance. Inheritance is an OOP property that allows us to derive a new class (subclass) from an existing class (superclass). The subclass inherits the attributes and methods of the superclass.

Now, if the same method is defined in both the superclass and the subclass, then the method of the subclass class overrides the method of the superclass. This is known as method overriding.

Example 1: Method Overriding

class Animal < public void displayInfo() < System.out.println("I am an animal."); >> class Dog extends Animal < @Override public void displayInfo() < System.out.println("I am a dog."); >> class Main < public static void main(String[] args) < Dog d1 = new Dog(); d1.displayInfo(); >> 

In the above program, the displayInfo() method is present in both the Animal superclass and the Dog subclass.

When we call displayInfo() using the d1 object (object of the subclass), the method inside the subclass Dog is called. The displayInfo() method of the subclass overrides the same method of the superclass.

Working of method overriding in Java.

Notice the use of the @Override annotation in our example. In Java, annotations are the metadata that we used to provide information to the compiler. Here, the @Override annotation specifies the compiler that the method after this annotation overrides the method of the superclass.

It is not mandatory to use @Override . However, when we use this, the method should follow all the rules of overriding. Otherwise, the compiler will generate an error.

Java Overriding Rules

  • Both the superclass and the subclass must have the same method name, the same return type and the same parameter list.
  • We cannot override the method declared as final and static .
  • We should always override abstract methods of the superclass (will be discussed in later tutorials).

super Keyword in Java Overriding

A common question that arises while performing overriding in Java is:

Can we access the method of the superclass after overriding?

Well, the answer is Yes. To access the method of the superclass from the subclass, we use the super keyword.

Example 2: Use of super Keyword

class Animal < public void displayInfo() < System.out.println("I am an animal."); >> class Dog extends Animal < public void displayInfo() < super.displayInfo(); System.out.println("I am a dog."); >> class Main < public static void main(String[] args) < Dog d1 = new Dog(); d1.displayInfo(); >> 

Источник

Полиморфизм и переопределение

— Этот как корова, только больше и плавает. Кстати, киты произошли от коров. Ну, или имели общего с ними предка. Не столь важно.

Полиморфизм и переопределение - 1

— Так вот. Хочу рассказать тебе об еще одном очень мощном инструменте ООП – это полиморфизм . У него есть особенности.

1) Переопределение метода.

Представь, что ты для игры написал класс «Корова». В нем есть много полей и методов. Объекты этого класса могут делать разные вещи: идти, есть, спать. Еще коровы звонят в колокольчик, когда ходят. Допустим, ты реализовал в классе все до мелочей.

Полиморфизм и переопределение - 2

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

Ты начал проектировать класс «Кит» и понял, что он лишь немного отличается от класса «Корова». Логика работы обоих классов очень похожа, и ты решил использовать наследование.

Класс «Корова» идеально подходит на роль класса-родителя, там есть все необходимые переменные и методы. Достаточно только добавить киту возможность плавать. Но есть проблема: у твоего кита есть ноги, рога и колокольчик. Ведь эта функциональность реализована внутри класса «Корова». Что тут можно сделать?

Полиморфизм и переопределение - 3

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

Полиморфизм и переопределение - 4

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

class Cow < public void printColor() < System.out.println("Я - белая"); >public void printName() < System.out.println("Я - корова"); >> class Whale extends Cow < public void printName() < System.out.println("Я - кит"); >>
public static void main(String[] args)
public static void main(String[] args)

После наследования класса Cow и переопределения метода printName , класс Whale фактически содержит такие данные и методы:

class Whale < public void printColor() < System.out.println("Я - белая"); >public void printName() < System.out.println("Я - кит"); >>

2) Но это еще не все.

— Предположим в классе Cow есть метод printAll , который вызывает два других метода, тогда код будет работать так:

На экран будет выведена надпись Я – белая Я – кит

class Cow < public void printAll() < printColor(); printName(); >public void printColor() < System.out.println("Я - белая"); >public void printName() < System.out.println("Я - корова"); >> class Whale extends Cow < public void printName() < System.out.println("Я - кит"); >>
public static void main(String[] args)

Обрати внимание, когда вызываются метод printAll() написанный в классе Cow, у объекта типа Whale, то будет использован метод printName класса Whale , а не Cow.

Главное, не в каком классе написан метод, а какой тип (класс) объекта, у которого этот метод вызван.

— Наследовать и переопределять можно только нестатические методы. Статические методы не наследуются и, следовательно, не переопределяются.

Вот как выглядит класс Whale после применения наследования и переопределения методов:

class Whale < public void printAll() < printColor(); printName(); > public void printColor() < System.out.println("Я - белая"); >public void printName() < System.out.println("Я - кит"); >>

3) Приведение типов.

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

public static void main(String[] args) < Whale whale = new Whale(); whale.printColor(); >
public static void main(String[] args) < Cow cow = new Whale(); cow.printColor(); >
public static void main(String[] args) < Object o = new Whale(); System.out.println(o.toString()); >

— Очень интересно. А зачем это может понадобиться?

— Это ценное свойство. Позже ты поймешь, что очень, очень ценное.

4) Вызов метода объекта (динамическая диспетчеризация методов).

public static void main(String[] args) < Whale whale = new Whale(); whale.printName(); >
public static void main(String[] args) < Cow cow = new Whale(); cow.printName(); >

Обрати внимание, что на то, какой именно метод printName вызовется, от класса Cow или Whale, влияет не тип переменной, а тип – объекта, на который она ссылается.

В переменной типа Cow сохранена ссылка на объект типа Whale, и будет вызван метод printName, описанный в классе Whale.

— Это не просто для понимания.

— Да, это не очень очевидно. Запомни главное правило:

Набор методов, которые можно вызвать у переменной, определяется типом переменной. А какой именно метод/какая реализация вызовется, определяется типом/классом объекта, ссылку на который хранит переменная.

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

5) Расширение и сужение типов.

Для ссылочных типов, т.е. классов, приведение типов работает не так, как для примитивных типов. Хотя у ссылочных типов тоже есть расширение и сужение типа. Пример:

Cow cow = new Whale(); if (cow instanceof Whale) < Whale whale = (Whale) cow; >
Cow cow = new Cow(); Whale whale = (Whale) cow; //exception

6) А теперь еще на закуску. Вызов оригинального метода

Иногда тебе хочется не заменить унаследованный метод на свой при переопределении метода, а лишь немного дополнить его.

В этом случае очень хочется исполнить в новом методе свой код и вызвать этот же метод, но базового класса. И такая возможность в Java есть. Делается это так: super.method() .

class Cow < public void printAll() < printColor(); printName(); > public void printColor() < System.out.println("Я – белый"); >public void printName() < System.out.println("Я – корова"); >> class Whale extends Cow < public void printName() < System.out.print("Это неправда: "); super.printName(); System.out.println("Я – кит"); > >
public static void main(String[] args)< Whale whale = new Whale(); whale.printAll(); >

— Гм. Ничего себе лекция. Мои робо-уши чуть не расплавились.

— Да, это не простой материал, он один из самых сложных. Профессор обещал подкинуть ссылок на материалы других авторов, чтобы ты, если все-таки что-то не поймешь, мог устранить этот пробел.

Источник

Оцените статью