Overriding vs Hiding Java-Confused

Jestem zdezorientowany co do tego, czym przesłonięcie różni się od ukrywania w Javie. Czy ktoś może podać więcej szczegółów na temat ich różnic? Czytałem Java Tutorial ale przykładowy kod wciąż mnie zdezorientował.

Żeby było jaśniej, rozumiem to dobrze. Mój problem polega na tym, że nie widzę różnicy w ukrywaniu, z wyjątkiem faktu, że jeden znajduje się na poziomie instancji, a drugi na poziomie klasy.

Przeglądanie samouczka Java kod:

public class Animal {
    public static void testClassMethod() {
        System.out.println("Class" + " method in Animal.");
    }
    public void testInstanceMethod() {
        System.out.println("Instance " + " method in Animal.");
    }
}

Wtedy mamy podklasę Cat:

public class Cat extends Animal {
    public static void testClassMethod() {
        System.out.println("The class 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();
    }
}

Potem mówią:

Wyjście z tego programu jest następujące:

Metoda klasy u zwierząt.

Metoda instancji w Cat.

Dla mnie fakt, że wywołanie metody klasy testClassMethod() bezpośrednio z klasy Animal wykonuje metodę w klasie Animal jest dość oczywisty, nic specjalnego. Następnie nazywają testInstanceMethod() od odniesienia do myCat, więc znowu dość oczywiste że metoda wykonywana jest wtedy w instancji Cat.

Z tego co widzę, ukrywanie połączenia zachowuje się jak nadrzędne, więc po co to rozróżniać? Jeśli uruchamiam ten kod używając powyższych klas:

Cat.testClassMethod();

I ' ll get: metoda klasowa w kat. Ale jeśli usunę testClassMethod() z Cat, to dostanę: metoda klasowa u zwierząt.

Który pokazuje mi, że pisanie statycznej metody, z tym samym podpisem co w rodzicu, w podklasie pretty wiele z nich ma obejście.

Mam nadzieję, że wyjaśnię, gdzie jestem zdezorientowany i ktoś może rzucić trochę światła. Z góry bardzo dziękuję!

Author: CarenRose, 2012-05-15

17 answers

Overriding zasadniczo obsługuje późne wiązanie. W związku z tym decyduje się w czasie wykonywania, która metoda zostanie wywołana. Jest dla metod niestatycznych.

Ukrywanie jest dla wszystkich innych członków (metody statyczne, instancje, statyczne). Opiera się na wczesnym wiązaniu. Dokładniej, metoda lub element, który ma być wywołany lub użyty, jest ustalana w czasie kompilacji.

W twoim przykładzie, pierwsze wywołanie Animal.testClassMethod() jest wywołaniem metody static, stąd jest prawie pewne, która metoda będzie dzwoniłem.

W drugim wywołaniu, myAnimal.testInstanceMethod(), wywołujesz niestatyczną metodę. To się nazywa polimorfizm czasowy. Nie jest ustalane do czasu uruchomienia, która metoda ma być wywołana.

Aby uzyskać dalsze wyjaśnienia, przeczytaj nadpisywanie Vs ukrywanie.

 103
Author: Kazekage Gaara,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-12-05 21:31:47

Metody statyczne są ukryte, metody niestatyczne są nadrzędne. Różnica jest zauważalna, gdy wywołania nie są kwalifikowane" coś () " vs " to.coś ()".

Wydaje mi się, że nie potrafię tego opisać słowami, więc oto przykład:

public class Animal {

    public static void something() {
        System.out.println("animal.something");
    }

    public void eat() {
        System.out.println("animal.eat");
    }

    public Animal() {
        // This will always call Animal.something(), since it can't be overriden, because it is static.
        something();
        // This will call the eat() defined in overriding classes.
        eat();
    }

}


public class Dog extends Animal {

    public static void something() {
        // This method merely hides Animal.something(), making it uncallable, but does not override it, or alter calls to it in any way.
        System.out.println("dog.something");
    }

    public void eat() {
        // This method overrides eat(), and will affect calls to eat()
        System.out.println("dog.eat");
    }

    public Dog() {
        super();
    }

    public static void main(String[] args) {
        new Dog();
    }

}

Wyjście:

animal.something
dog.eat
 19
Author: WhyNotHugo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-05-15 04:28:22

To jest różnica między nadpisywaniem a ukrywaniem,

  1. Jeśli obie metody w klasie nadrzędnej i klasie podrzędnej są metodą instancji, wywołują one nadpisania.
  2. Jeśli obie metody w klasie macierzystej i klasie potomnej są metodą statyczną, wywołane zostanie ukrywanie.
  3. jedna metoda nie może być statyczna w rodzicu i jako instancja w dziecku. i visa versa.

Tutaj wpisz opis obrazka

 14
Author: Rudy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-05-15 04:25:32

Jeśli dobrze rozumiem twoje pytanie, to odpowiedź brzmi: "już jesteś nadrzędny".

", który pokazuje mi, że zapisanie statycznej metody o tej samej nazwie, co w rodzicu, w podklasie praktycznie powoduje nadpisanie."

Jeśli napiszesz metodę w podklasie o dokładnie takiej samej nazwie jak metoda w superklasie, nadpisze ona metodę superklasy. Adnotacja @ Override nie jest wymagana do nadpisania metody. Sprawia jednak, że kod jest bardziej czytelny i wymusza kompilator, aby sprawdzić, czy rzeczywiście nadpisujesz metodę(i nie pomylił pisowni metody podklasy na przykład).

 3
Author: thagorn,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-05-15 04:17:51

Nadpisywanie odbywa się tylko przy użyciu metod instancji. Jeżeli typem zmiennej referencyjnej jest zwierzę, a obiektem jest Cat, to metoda instancji jest wywoływana z Cat (jest to nadrzędne). Dla tego samego obiektu acat stosowana jest metoda klasowa Animal.

public static void main(String[] args) {
    Animal acat = new Cat();
    acat.testInstanceMethod();
    acat.testClassMethod();

}

Wyjście To:

The instance method in Cat.
Class method in Animal.
 3
Author: yiannis,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-05-15 04:34:55
public class First {

    public void Overriding(int i) {  /* will be overridden in class Second */ }

    public static void Hiding(int i) {  /* will be hidden in class Second
                                           because it's static */ }
}


public class Second extends First {

    public void Overriding(int i) {  /* overridden here */  }

    public static void Hiding(int i) {  /* hides method in class First
                                           because it's static */ } 
}

Zasada zapamiętywania jest prosta: metoda w klasie rozszerzającej can ' t change static to void and nie można zmienić void na static. Spowoduje to błąd kompilacji.

Ale jeśli void Name zostanie zmieniona na void Name to jest nadrzędne.

I jeśli static Name zostanie zmieniona na static Name to się ukrywa. (Można wywołać zarówno statyczną metodę podklasy, jak i metodę klasy nadrzędnej, w zależności od typu odniesienia użytego do wywołania metody.)

 2
Author: p.karnaukhov,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-02-12 13:01:56

W tym fragmencie kodu używam modyfikatora dostępu "prywatny" zamiast "statyczny", aby pokazać różnicę między ukrywaniem metod a nadpisywaniem metod.

class Animal {
// Use 'static' or 'private' access modifiers to see how method hiding work.
private void testInstancePrivateMethod(String source) {
    System.out.println("\tAnimal: instance Private method calling from "+source);
}
public void testInstanceMethodUsingPrivateMethodInside() {
    System.out.println("\tAnimal: instance Public method with using of Private method.");
    testInstancePrivateMethod( Animal.class.getSimpleName() );
}

// Use default, 'protected' or 'public' access modifiers to see  how method overriding work.
protected void testInstanceProtectedMethod(String source) {
    System.out.println("\tAnimal: instance Protected method calling from "+source);
}
public void testInstanceMethodUsingProtectedMethodInside() {
    System.out.println("\tAnimal: instance Public method with using of Protected method.");
    testInstanceProtectedMethod( Animal.class.getSimpleName() );
  } 
}  


public class Cat extends Animal {
private void testInstancePrivateMethod(String source) {
    System.out.println("Cat: instance Private method calling from " + source );
}
public void testInstanceMethodUsingPrivateMethodInside() {
    System.out.println("Cat: instance Public method with using of Private method.");
    testInstancePrivateMethod( Cat.class.getSimpleName());
    System.out.println("Cat: and calling parent after:");
    super.testInstanceMethodUsingPrivateMethodInside();
}

protected void testInstanceProtectedMethod(String source) {
    System.out.println("Cat: instance Protected method calling from "+ source );
}
public void testInstanceMethodUsingProtectedMethodInside() {
    System.out.println("Cat: instance Public method with using of Protected method.");
    testInstanceProtectedMethod(Cat.class.getSimpleName());
    System.out.println("Cat: and calling parent after:");
    super.testInstanceMethodUsingProtectedMethodInside();
}

public static void main(String[] args) {
    Cat myCat = new Cat();
    System.out.println("----- Method hiding -------");
    myCat.testInstanceMethodUsingPrivateMethodInside();
    System.out.println("\n----- Method overriding -------");
    myCat.testInstanceMethodUsingProtectedMethodInside();
}
}

Wyjście:

----- Method hiding -------
Cat: instance Public method with using of Private method.
Cat: instance Private method calling from Cat
Cat: and calling parent after:
   Animal: instance Public method with using of Private method.
   Animal: instance Private method calling from Animal

----- Method overriding -------
Cat: instance Public method with using of Protected method.
Cat: instance Protected method calling from Cat
Cat: and calling parent after:
   Animal: instance Public method with using of Protected method.
Cat: instance Protected method calling from Animal
 1
Author: Rustem Zhunusov,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-11-16 14:17:18

Na podstawie moich ostatnich badań Java

  • metoda nadpisywanie , gdy podklasa ma tę samą metodę z tym samym podpisem w podklasie.
  • metoda ukrywanie , gdy podklasa ma tę samą nazwę metody, ale inny parametr. W takim przypadku nie nadpisujesz metody nadrzędnej, ale ją ukrywasz.

Przykład z książki OCP Java 7, strona 70-71:

public class Point {
  private int xPos, yPos;
  public Point(int x, int y) {
        xPos = x;
        yPos = y;
  }

  public boolean equals(Point other){
  .... sexy code here ...... 
  }

  public static void main(String []args) {
   Point p1 = new Point(10, 20);
   Point p2 = new Point(50, 100);
   Point p3 = new Point(10, 20);
   System.out.println("p1 equals p2 is " + p1.equals(p2));
   System.out.println("p1 equals p3 is " + p1.equals(p3));
   //point's class equals method get invoked
  }
}

Ale jeśli napiszemy następującą główną:

  public static void main(String []args) {
   Object p1 = new Point(10, 20);
   Object p2 = new Point(50, 100);
   Object p3 = new Point(10, 20);
   System.out.println("p1 equals p2 is " + p1.equals(p2));
   System.out.println("p1 equals p3 is " + p1.equals(p3));
   //Object's class equals method get invoked
  }

W drugim głównym, my używając klasy obiektu jako typu statycznego, więc kiedy wywołujemy metodę equal w obiekcie punktowym, to czeka na przyjście klasy punktowej jako parametru,ale obiekt nadchodzi. Tak więc klasa obiektu jest równa uruchomionej metodzie, ponieważ mamy tam równe (obiekt o). W tym przypadku Klasa punktu równa się nie nadpisuje, lecz ukrywa klasę obiektu równa się metoda .

 0
Author: Karoly,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-09-10 09:16:59
public class Parent {

  public static void show(){
    System.out.println("Parent");
  }
}

public class Child extends Parent{

  public static void show(){
    System.out.println("Child");
  }
}

public class Main {

public static void main(String[] args) {
    Parent parent=new Child();
    parent.show(); // it will call parent show method
  }
}

// We can call static method by reference ( as shown above) or by using class name (Parent.show())
 0
Author: Deepak,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-04-23 10:10:38

Linked java tutorial page explains the concept of overridering and hiding

Metoda instancji w podklasie z tym samym podpisem (nazwa, plus numer i typ jej parametrów) i typ zwracany jako metoda instancji w klasie nadrzędnej nadpisuje metodę klasy nadrzędnej.

Jeśli podklasa definiuje statyczną metodę z tym samym podpisem co statyczna metoda w superklasie, to metoda w podklasie ukrywa metodę w superklasie.

The rozróżnienie między ukrywaniem statycznej metody a nadpisywaniem instancji ma istotne implikacje:

  1. Wersja metody nadpisanej instancji, która zostanie wywołana, jest tą w podklasie.
  2. wersja ukrytej statycznej metody, która zostanie wywołana zależy od tego, czy jest wywoływana z klasy nadrzędnej czy podklasy.

Wracając do twojego przykładu:

Animal myAnimal = myCat;

 /* invokes static method on Animal, expected. */
 Animal.testClassMethod(); 

 /* invokes child class instance method (non-static - it's overriding) */
 myAnimal.testInstanceMethod();

Powyższe stwierdzenie nie pokazuje jeszcze ukrywania.

Teraz Zmień kod jak poniżej, aby uzyskać inny wynik:

  Animal myAnimal = myCat;
  
  /* Even though myAnimal is Cat, Animal class method is invoked instead of Cat method*/
  myAnimal.testClassMethod();
  
  /* invokes child class instance method (non-static - it's overriding) */
  myAnimal.testInstanceMethod();
 0
Author: Ravindra babu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-06-20 09:12:55

Oprócz przykładów wymienionych powyżej, poniżej znajduje się mały przykładowy kod wyjaśniający różnicę między ukrywaniem i nadpisywaniem:

public class Parent {

    // to be hidden (static)
    public static String toBeHidden() {
        return "Parent";
    }

    // to be overridden (non-static)
    public String toBeOverridden() {
        return "Parent";
    }

    public void printParent() {
        System.out.println("to be hidden: " + toBeHidden());
        System.out.println("to be overridden: " + toBeOverridden());
    }
}

public class Child extends Parent {

    public static String toBeHidden() {
        return "Child";
    }

    public String toBeOverridden() {
        return "Child";
    }

    public void printChild() {
        System.out.println("to be hidden: " + toBeHidden());
        System.out.println("to be overridden: " + toBeOverridden());
    }
}

public class Main {

    public static void main(String[] args) {
        Child child = new Child();
        child.printParent();
        child.printChild();
    }
}

Wywołanie child.printParent() wyjścia:
do ukrycia: rodzic
to be overridden: Child

Wywołanie child.printChild() wyjścia:
do ukrycia: Dziecko
to be overridden: Child

Jak widać z powyższych wyjść (szczególnie pogrubionych zaznaczonych wyjść), ukrywanie metod zachowuje się inaczej niż / align = "left" /

Java pozwala zarówno na ukrywanie, jak i nadpisywanie tylko dla metod. Ta sama zasada nie ma zastosowania do zmiennych. Zmienne nadrzędne nie są dozwolone, więc zmienne mogą być tylko Ukryte (nie ma różnicy między zmienną statyczną i niestatyczną). Poniższy przykład pokazuje, jak metoda getName() jest nadpisana, a zmienna name jest ukryta:

public class Main {

    public static void main(String[] args) {
        Parent p = new Child();
        System.out.println(p.name); // prints Parent (since hiding)
        System.out.println(p.getName()); // prints Child (since overriding)
    }
}

class Parent {
    String name = "Parent";

    String getName() {
        return name;
    }
}

class Child extends Parent {
    String name = "Child";

    String getName() {
        return name;
    }
}
 0
Author: Nurettin Armutcu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-09-16 18:48:26

W trybie runtime potomna wersja nadpisanej metody jest zawsze wykonywana dla instancji niezależnie od tego, czy wywołanie metody jest defioryzowane w metodzie klasy rodzica czy potomka. W tym sposób, Metoda rodzica nigdy nie jest używana, chyba że jawne wywołanie metody rodzica jest odwołuje się, używając składni Imię i nazwisko rodziców.metoda (). Alternatywnie, w czasie wykonywania rodzic wersja ukrytej metody jest zawsze wykonywana, jeżeli wywołanie metody jest zdefiniowane w zajęcia dla rodziców.

 0
Author: Carrieukie,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-27 13:45:20

W metodzie nadpisywanie rozdzielczość metody jest wykonywana przez JVM na podstawie obiektu runtime. Podczas gdy w ukrywaniu metod rozdzielczość metody jest dokonywana przez kompilator na podstawie referencji. Zatem

Jeśli kod zostałby napisany jako,

public static void main(String[] args) {
        Animal myCat = new Cat();        
        myCat.testClassMethod();        
    }

Wyjście byłoby jak poniżej:
Metoda klasowa u zwierząt.

 0
Author: SagarS,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-04-07 13:51:39

Nazywa się to ukrywaniem, ponieważ kompilator ukrywa implementację metody super klasy, gdy podklasa ma tę samą statyczną metodę.

Kompilator nie ma ograniczonej widoczności dla nadpisanych metod i tylko podczas wykonywania decyduje, która z nich zostanie użyta.

 0
Author: Gadam,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-09-03 22:44:30

To jest różnica między nadpisywaniem a ukrywaniem:

Animal a = new Cat ();

A. testClassMethod() wywoła metodę w klasie nadrzędnej, ponieważ jest to przykład ukrywania metody. Metoda, która ma być wywołana, jest określana przez typ zmiennej referencyjnej i ustalana w czasie kompilacji.

A. testInstanceMethod() wywoła metodę w klasie potomnej, ponieważ jest to przykład nadpisywania metody. Wywołana metoda jest określona przez obiekt, który służy do wywołania metoda w czasie wykonywania.

 0
Author: Kinshuk,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-07-16 12:00:30

Myślę, że nie jest to jeszcze do końca wyjaśnione. Zobacz poniższy przykład.

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");
    }
}


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) {
        Animal myCat = new Cat();
        Cat myCat2 = new Cat();
        myCat.testClassMethod();
        myCat2.testClassMethod();
        
        
        myCat.testInstanceMethod();
        myCat2.testInstanceMethod();
    }
}

Wynik będzie następujący.

The static method in Animal
The static method in Cat
The instance method in Cat
The instance method in Cat
 0
Author: Gihan Gamage,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-12-03 11:19:34

Jak ukrywanie statycznych metod dzieje się w Javie? Klasa kota rozszerza klasę zwierząt. Tak więc w klasie Cat będą miały obie metody statyczne (mam na myśli metodę statyczną klasy potomnej i metodę statyczną klasy rodzica) Ale w jaki sposób JVM ukrywa metodę statyczną rodzica? Jak sobie radzi w stercie i stosie?

 -1
Author: user3924979,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-07-09 04:00:22