Что такое метод сокрытия в Java? Даже объяснение JavaDoc сбивает с толку

Javadoc говорит:

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

не звонит мне в звонок. Любой четкий пример, показывающий значение этого, будет высоко оценен.

8 ответов

Решение
public class Animal {
    public static void foo() {
        System.out.println("Animal");
    }
}

public class Cat extends Animal {
    public static void foo() {  // hides Animal.foo()
        System.out.println("Cat");
    }
}

Вот, Cat.foo() Говорят, чтобы скрыть Animal.foo(), Сокрытие не работает как переопределение, потому что статические методы не полиморфны. Так что произойдет следующее:

Animal.foo(); // prints Animal
Cat.foo(); // prints Cat

Animal a = new Animal();
Animal b = new Cat();
Cat c = new Cat();
Animal d = null;

a.foo(); // should not be done. Prints Animal because the declared type of a is Animal
b.foo(); // should not be done. Prints Animal because the declared type of b is Animal
c.foo(); // should not be done. Prints Cat because the declared type of c is Cat
d.foo(); // should not be done. Prints Animal because the declared type of d is Animal

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

Сравните это с методами экземпляра, которые являются полиморфными и поэтому переопределяются. Вызываемый метод зависит от конкретного типа объекта во время выполнения:

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

public class Cat extends Animal {
    public void foo() { // overrides Animal.foo()
        System.out.println("Cat");
    }
}

Тогда произойдет следующее:

Animal a = new Animal();
Animal b = new Cat();
Animal c = new Cat();
Animal d = null;

a.foo(); // prints Animal
b.foo(); // prints Cat
c.foo(); // prints Cat
d.foo(): // throws NullPointerException

Прежде всего, что подразумевается под методом Hiding?

Скрытие метода означает, что подкласс определил метод класса с той же сигнатурой, что и метод класса в суперклассе. В этом случае метод суперкласса скрыт подклассом. Это означает, что: версия выполняемого метода НЕ будет определяться объектом, который используется для его вызова. Фактически это будет определяться типом ссылочной переменной, используемой для вызова метода.

Что подразумевается под переопределением метода?

Переопределение метода означает, что подкласс определил метод экземпляра с той же сигнатурой и типом возврата (включая ковариантный тип), что и метод экземпляра в суперклассе. В этом случае метод суперкласса переопределяется (заменяется) подклассом. Это означает, что: Версия выполняемого метода будет определяться объектом, который используется для его вызова. Он не будет определяться типом ссылочной переменной, используемой для вызова метода.

Почему статические методы не могут быть переопределены?

Потому что статические методы разрешаются статически (т.е. во время компиляции) на основе класса, к которому они обращаются, а не динамически, как в случае с методами экземпляра, которые разрешаются полиморфно на основе типа времени выполнения объекта.

Как получить доступ к статическим методам?

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

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

class Super
{
  public static void foo(){System.out.println("I am foo in Super");}
  public void bar(){System.out.println("I am bar in Super");}
}
class Child extends Super
{
  public static void foo(){System.out.println("I am foo in Child");}//Hiding
  public void bar(){System.out.println("I am bar in Child");}//Overriding
  public static void main(String[] args)
  {
     Super sup = new Child();//Child object is reference by the variable of type Super
     Child child = new Child();//Child object is referenced by the variable of type Child
     sup.foo();//It will call the method of Super.
     child.foo();//It will call the method of Child.

     sup.bar();//It will call the method of Child.
     child.bar();//It will call the method of Child again.
  }
}

Выход

I am foo in Super
I am foo in Child
I am bar in Child
I am bar in Child

Понятно, как указано, так как foo это метод класса, так что версия foo Вызванный будет определяться типом ссылочной переменной (то есть Super или Child), ссылающейся на объект Child, Если на него ссылается Super переменная тогда foo из Super называется. И если на него ссылается Child переменная тогда foo из Child называется.
Принимая во внимание, что
поскольку bar это метод экземпляра, поэтому версия bar вызывается исключительно определяется объектом (т.е. Child), который используется для его вызова. Неважно, через какую ссылочную переменную (Super или же Child) это называется, метод, который будет вызываться всегда Child,

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

Скрытие метода означает, что неквалифицированный вызов этого имени в области действия этого класса (т. Е. В теле любого из его методов или при наличии имени этого класса) теперь будет вызывать совершенно другую функцию, требующую квалификации для доступа к статическому методу с тем же именем из родительского класса.

Подробное описание Java Inheritance: перезаписанные или скрытые методы

Если подкласс определяет метод класса с той же сигнатурой, что и у метода класса в суперклассе, метод в подклассе скрывает метод в суперклассе.

Я считаю, что скрытые методы находятся в статическом контексте. Статические методы не переопределяются сами по себе, потому что разрешение вызовов методов выполняется компилятором во время компиляции. Таким образом, если вы определяете статический метод в базовом классе с той же сигнатурой, что и в родительском классе, то метод в подклассе скрывает метод, унаследованный от суперкласса.

class Foo {
  public static void method() {
     System.out.println("in Foo");
  }
}

class Bar extends Foo {
   public static void method() {
    System.out.println("in Bar");
  }
}

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

Скрытие в родительском классе имеет статический метод с именем Foo, а подкласс также имеет статический метод с именем Foo.

В другом сценарии родительский объект имеет статический метод с именем Cat, а подкласс имеет метод экземпляра с именем Cat. (статический и экземпляр с одинаковой подписью не может смешиваться).

public class Animal {

  public static String getCat() { return "Cat"; }

  public boolean isAnimal() { return true; }
}

public class Dog extends Animal {

  // Method hiding
  public static String getCat() { }

  // Not method hiding
  @Override
  public boolean isAnimal() { return false; }
}

Когда супер / родительский класс и дочерний / дочерний класс содержат один и тот же статический метод, включая одинаковые параметры и подпись. Метод в суперклассе будет скрыт методом в подклассе. Это известно как метод сокрытия.

Пример:1

class Demo{
   public static void staticMethod() {
      System.out.println("super class - staticMethod");
   }
}
public class Sample extends Demo {

   public static void main(String args[] ) {
      Sample.staticMethod(); // super class - staticMethod
   }
}

Пример:2 - Скрытие метода

class Demo{
   public static void staticMethod() {
      System.out.println("super class - staticMethod");
   }
}
public class Sample extends Demo {
   public static void staticMethod() {
      System.out.println("sub class - staticMethod");
   }
   public static void main(String args[] ) {
      Sample.staticMethod(); // sub class - staticMethod
   }
}
 class P
    {
    public static  void m1()
    {
    System.out.println("Parent");
    }
}
    class C extends P
    {
    public static void m1()
    {
    System.out.println("Child");
    }
}
class Test{
    public static void main(String args[])
    {
    Parent p=new Parent();//Parent
    Child c=new Child();  //Child
    Parent p=new Child();  //Parent
    }
    }

If the both parent and child class method are static the compiler is responsible for method resolution based on reference type

class Parent
{
public void m1()
{
System.out.println("Parent");
}}
class Child extends Parent
{
public void m1()
{
System.out.println("Child")
}
}
class Test
{
public static void main(String args[])
{
Parent p=new Parent(); //Parent 
Child c=new Child();   //Child
Parent p=new Child();  //Child
}
}

If both method are not static  jvm is responsible for method resolution based on run time object

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

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