การลบล้างและการซ่อน Java - สับสน


88

ฉันสับสนว่าการลบล้างแตกต่างจากการซ่อนใน Java อย่างไร ใครช่วยให้รายละเอียดเพิ่มเติมว่าสิ่งเหล่านี้แตกต่างกันอย่างไร ฉันอ่านJava Tutorialแต่โค้ดตัวอย่างยังทำให้ฉันสับสน

เพื่อให้ชัดเจนยิ่งขึ้นฉันเข้าใจการลบล้างได้ดี ปัญหาของฉันคือฉันไม่เห็นว่าการซ่อนแตกต่างกันอย่างไรยกเว้นความจริงที่ว่าหนึ่งอยู่ในระดับอินสแตนซ์ในขณะที่อีกอันอยู่ในระดับชั้นเรียน

ดูโค้ดสอน Java:

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

จากนั้นเรามีคลาสย่อย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();
    }
}

จากนั้นพวกเขาพูดว่า:

ผลลัพธ์จากโปรแกรมนี้มีดังนี้:

วิธีการคลาสในสัตว์

วิธีการอินสแตนซ์ใน Cat

สำหรับฉันความจริงที่ว่าการเรียกเมธอดคลาสtestClassMethod()โดยตรงจากAnimalคลาสเรียกใช้เมธอดในAnimalคลาสนั้นค่อนข้างชัดเจนไม่มีอะไรพิเศษที่นั่น จากนั้นพวกเขาเรียกtestInstanceMethod()จากการอ้างอิงถึงmyCatดังนั้นจึงค่อนข้างชัดเจนอีกครั้งว่าวิธีการที่ดำเนินการนั้นเป็นวิธีที่อยู่ในตัวอย่างของCat .

จากสิ่งที่ฉันเห็นการซ่อนการโทรทำงานเหมือนกับการลบล้างดังนั้นทำไมจึงสร้างความแตกต่าง หากฉันเรียกใช้รหัสนี้โดยใช้คลาสด้านบน:

Cat.testClassMethod();

ฉันจะได้รับ: วิธีการเรียนใน Cat แต่ถ้าฉันลบออกtestClassMethod()จาก Cat ฉันจะได้รับ: เมธอดคลาสใน Animal

ซึ่งแสดงให้ฉันเห็นว่าการเขียนวิธีการแบบคงที่โดยมีลายเซ็นเดียวกับในพาเรนต์ในคลาสย่อยนั้นค่อนข้างจะลบล้างได้

หวังว่าฉันจะอธิบายให้ชัดเจนว่าฉันสับสนตรงไหนและใครบางคนสามารถส่องแสงได้ ขอบคุณมากล่วงหน้า!


คำตอบ:


103

การลบล้างโดยทั่วไปรองรับการผูกล่าช้า ดังนั้นจึงมีการตัดสินใจในเวลาดำเนินการว่าจะเรียกวิธีใด เป็นวิธีการที่ไม่คงที่

การซ่อนมีไว้สำหรับสมาชิกอื่น ๆ ทั้งหมด (วิธีการแบบคงที่สมาชิกอินสแตนซ์สมาชิกแบบคงที่) มันขึ้นอยู่กับการผูกในช่วงต้น ชัดเจนยิ่งขึ้นวิธีการหรือสมาชิกที่จะเรียกหรือใช้จะถูกตัดสินใจในช่วงเวลารวบรวม

ในตัวอย่างของคุณการโทรครั้งแรกAnimal.testClassMethod()เป็นการเรียกใช้staticเมธอดดังนั้นจึงค่อนข้างแน่ใจว่าจะเรียกวิธีใด

ในการโทรครั้งที่สองmyAnimal.testInstanceMethod()คุณเรียกวิธีการแบบไม่คงที่ นี่คือสิ่งที่คุณเรียกว่าความหลากหลายแบบรันไทม์ ยังไม่ตัดสินใจจนกว่าจะถึงเวลาเรียกใช้ว่าจะเรียกใช้วิธีใด

สำหรับคำชี้แจงเพิ่มเติมอ่านเอาชนะ Vs ซ่อน


3
ขอบคุณสำหรับคำตอบด่วนสิ่งนี้ทำให้กระจ่าง! ฉันสังเกตว่าในตัวอย่าง JavaRanch พวกเขาใช้ตัวแปรเพื่อเรียกเมธอดคลาสแทนการใช้คลาสโดยตรงซึ่งทำให้เข้าใจง่ายขึ้น ผมคิดว่าใน Java กวดวิชาที่พวกเขาใช้ในชั้นเรียนโดยตรงเพราะใช้อินสแตนซ์ที่จะเรียกวิธีการคงที่อาจจะไม่ปฏิบัติที่ดี แต่พวกเขาควรจะใช้myAnimal.testClassMethod ()แทนAnimal.testClassMethod ()
Lostlink

+1 เพื่อให้สามารถใส่คำได้อย่างเหมาะสมแทนที่จะเป็นตัวอย่าง! :)
WhyNotHugo

@Kazekage กาอาระมีความแตกต่างระหว่างการโอเวอร์โหลดและการซ่อนหรือไม่?
gstackoverflow

1
ฉันเห็นด้วยแน่นอนกับคำตอบ แต่แล้วprivate methodsล่ะ พวกเขาไม่สามารถอยู่ได้overriddenเนื่องจากคลาสย่อยไม่ทราบเกี่ยวกับการดำรงอยู่ของพวกเขา .. ดังนั้นพวกเขาอาจจะเป็นhiddenแทน
Paschalis

คำตอบยอดเยี่ยม! แม้ว่าคุณอาจเพิ่มตัวอย่างที่ coderanch เพื่อความสมบูรณ์ :)
Shubham Mittal

19

วิธีการคงที่ถูกซ่อนไว้วิธีการที่ไม่คงที่จะถูกลบล้าง ความแตกต่างที่น่าสังเกตเมื่อการโทรไม่ตรงตาม "something ()" vs "this.something ()"

ฉันดูเหมือนจะพูดไม่ออกจริงๆดังนั้นนี่คือตัวอย่าง:

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

}

เอาท์พุท:

animal.something
dog.eat

1
ตกลงแล้วจะเกิดอะไรขึ้นถ้าฉันเรียกว่า `` dog husky = new dog (); ' และhusky.Animal();จะเรียกมันว่าพิมพ์animal.somethingหรือdog.something ? ฉันเดาว่ามันผิดที่จะพูด ** ว่า** สิ่งนี้มักจะเรียก Animal.something ()
amarnath ทำร้าย

@amarnathharish คุณทำไม่ได้.Animal()จำไว้ว่าAnimal()เป็นผู้สร้าง
Dude156

และเพื่อเป็นการชี้แจงเพิ่มเติมสำหรับทุกคนที่สงสัยเหตุผลที่Animal's something()in Animal() always call something()เป็นเพราะการเรียกใช้วิธีการแบบคงที่ได้รับการแก้ไขในเวลารวบรวมแทนที่จะเป็นรันไทม์ ซึ่งหมายความว่าการเรียกวิธีแบบคงที่ในอยู่เสมอโดยปริยายเรียกAnimal() Animal.something()สิ่งนี้ค่อนข้างใช้งานง่ายถ้าคุณคิดเกี่ยวกับมัน: การเรียกใช้วิธีการแบบคงที่จะต้องนำหน้าด้วยชื่อคลาส (เช่นclassName.staticMethodName()) เว้นแต่การเรียกนั้นจะอยู่ในคลาสเดียวกัน
Dude156

14

นี่คือความแตกต่างระหว่างการลบล้างและการซ่อน

  1. ถ้าทั้งเมธอดในคลาสพาเรนต์และคลาสรองเป็นเมธอดอินสแตนซ์จะเรียกว่าการแทนที่
  2. หากทั้งสองเมธอดในคลาสพาเรนต์และคลาสย่อยเป็นเมธอดแบบคงที่จะเรียกว่าการซ่อน
  3. วิธีการหนึ่งไม่สามารถคงที่ในพาเรนต์และเป็นอินสแตนซ์ในเด็กได้ และวีซ่าในทางกลับกัน

ใส่คำอธิบายภาพที่นี่


3
คุณตัดและวางตารางนั้นโดยตรงจากบทช่วยสอนที่ OP กล่าวว่าไม่ได้ช่วยให้เขาเข้าใจ
wolfcastle

ตารางทำให้ชัดเจนมากในตัวอย่างไม่ได้พิจารณาทุกกรณี
tutak

3

หากฉันเข้าใจคำถามของคุณอย่างถูกต้องคำตอบก็คือ "คุณกำลังเอาชนะ"

"ซึ่งแสดงให้ฉันเห็นว่าการเขียนเมธอดแบบคงที่โดยใช้ชื่อเดียวกับในพาเรนต์ในคลาสย่อยนั้นค่อนข้างจะลบล้าง"

ถ้าคุณเขียนเมธอดในคลาสย่อยที่มีชื่อเดียวกับเมธอดในซูเปอร์คลาสมันจะแทนที่เมธอดของซูเปอร์คลาส คำอธิบายประกอบ @Override ไม่จำเป็นต้องใช้เพื่อแทนที่เมธอด อย่างไรก็ตามจะทำให้โค้ดของคุณอ่านง่ายขึ้นและบังคับให้คอมไพเลอร์ตรวจสอบว่าคุณกำลังลบล้างเมธอด (และไม่ได้สะกดผิดวิธีการคลาสย่อยเป็นต้น)


1
คำตอบนี้ไม่สามารถระบุอินสแตนซ์เทียบกับวิธีการคงที่เกี่ยวกับการลบล้าง / ซ่อน
Paul Bellora

3

การลบล้างเกิดขึ้นเฉพาะกับวิธีการของอินสแตนซ์ เมื่อชนิดของตัวแปรอ้างอิงคือ Animal และออบเจ็กต์คือ Cat เมธอดอินสแตนซ์จะถูกเรียกจาก Cat (ซึ่งเป็นการแทนที่) สำหรับออบเจ็กต์ acat เดียวกันจะใช้เมธอดคลาสของ Animal

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

}

ผลลัพธ์คือ:

The instance method in Cat.
Class method in Animal.

2
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 */ } 
}

กฎสำหรับการจำนั้นง่ายมากเมธอดในคลาสขยายไม่สามารถเปลี่ยนสแตติกเป็นโมฆะและไม่สามารถเปลี่ยนโมฆะเป็นสแตติกได้ มันจะทำให้เกิดข้อผิดพลาดในการคอมไพล์

แต่ถ้าvoid Nameเปลี่ยนvoid Nameเป็น Overriding

และถ้าstatic Nameเปลี่ยนstatic Nameเป็นซ่อน (ทั้งเมธอดแบบคงที่ของคลาสย่อยและหนึ่งในซูเปอร์คลาสสามารถเรียกได้ขึ้นอยู่กับประเภทของการอ้างอิงที่ใช้ในการเรียกเมธอด)


1

ในข้อมูลโค้ดนี้ฉันใช้ตัวแก้ไขการเข้าถึง 'ส่วนตัว' แทน 'คงที่' เพื่อแสดงความแตกต่างระหว่างวิธีการซ่อนและวิธีการลบล้าง

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

เอาท์พุต:

----- 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

สงสัยว่าทำไมถึงไม่ได้รับคะแนนโหวต.. คำตอบที่น่าชื่นชมมาก
amarnath ทำร้าย

0

จากการศึกษา Java ล่าสุดของฉัน

  • วิธีการแทนที่เมื่อคลาสย่อยมีวิธีการเดียวกันที่มีลายเซ็นเดียวกันในคลาสย่อย
  • การซ่อนเมธอดเมื่อคลาสย่อยมีชื่อเมธอดเหมือนกัน แต่พารามิเตอร์ต่างกัน ในกรณีนี้คุณไม่ได้ลบล้างเมธอดหลัก แต่ซ่อนไว้

ตัวอย่างจากหนังสือ OCP Java 7 หน้า 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
  }
}

แต่ถ้าเราเขียนหลักต่อไปนี้:

  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
  }

ในหลักที่สองเราใช้คลาส Object เป็นประเภทคงที่ดังนั้นเมื่อเราเรียก method ที่เท่าเทียมกันใน Point object มันกำลังรอให้คลาส Point มาถึงเป็นพารามิเตอร์ แต่ Object กำลังมา คลาสอ็อบเจ็กต์จึงเท่ากับเมธอดการรันเนื่องจากเรามีค่าเท่ากับ (อ็อบเจ็กต์ o) ที่นั่น ในกรณีนี้ระดับจุดเท่ากับแทนที่ dosen't แต่ระดับซ่อนวัตถุเท่ากับวิธีการ


0
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

หน้าบทช่วยสอน Java ที่เชื่อมโยงจะอธิบายแนวคิดของการลบล้างและซ่อน

วิธีการของอินสแตนซ์ในคลาสย่อยที่มีลายเซ็นเดียวกัน (ชื่อบวกหมายเลขและประเภทของพารามิเตอร์) และประเภทการส่งคืนเป็นวิธีการอินสแตนซ์ในซูเปอร์คลาสจะแทนที่เมธอดของซูเปอร์คลาส

หากคลาสย่อยกำหนดวิธีการแบบคงที่โดยมีลายเซ็นเดียวกันกับวิธีการแบบคงที่ในซูเปอร์คลาสดังนั้นวิธีการในคลาสย่อยจะซ่อนวิธีการหนึ่งในซูเปอร์คลาส

ความแตกต่างระหว่างการซ่อนเมธอดแบบคงที่และการแทนที่เมธอดอินสแตนซ์มีนัยสำคัญ:

  1. เวอร์ชันของเมธอดอินสแตนซ์ที่ถูกลบล้างซึ่งถูกเรียกใช้คือเวอร์ชันในคลาสย่อย
  2. เวอร์ชันของวิธีการคงที่ที่ซ่อนอยู่ซึ่งถูกเรียกใช้ขึ้นอยู่กับว่าถูกเรียกใช้จากซูเปอร์คลาสหรือคลาสย่อย

กลับมาที่ตัวอย่างของคุณ:

Animal myAnimal = myCat;

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

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

ข้อความข้างต้นยังไม่แสดงการซ่อน

ตอนนี้เปลี่ยนรหัสด้านล่างเพื่อให้ได้ผลลัพธ์ที่แตกต่างกัน:

  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();

ฉันพยายามทำความเข้าใจว่าคำว่าซ่อนตัวหมายถึงอะไร สิ่งที่ซ่อนอยู่คืออะไร? เมธอดแบบคงที่ในคลาส Parent ถูกซ่อนอยู่เนื่องจาก (คาดว่าน้อยที่สุด) จะถูกเรียกใช้หรือไม่? หรือวิธีการแบบคงที่ในคลาส Child ถูกซ่อนอยู่เนื่องจากไม่ได้รับการเรียกใช้?
แมงป่อง

0

นอกเหนือจากตัวอย่างข้างต้นแล้วนี่คือตัวอย่างโค้ดเล็ก ๆ เพื่อชี้แจงความแตกต่างระหว่างการซ่อนและการลบล้าง:

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

สายของchild.printParent()เอาท์พุท:
ถูกซ่อนไว้: ผู้ปกครอง
ที่จะแทนที่: เด็ก

การเรียกchild.printChild()เอาท์พุท:
ที่จะซ่อน: เด็ก
ที่จะถูกแทนที่: เด็ก

ดังที่ wee สามารถเห็นได้จากเอาต์พุตด้านบน (โดยเฉพาะเอาต์พุตที่ทำเครื่องหมายเป็นตัวหนา) การซ่อนเมธอดจะทำงานแตกต่างจากการลบล้าง

Java อนุญาตให้ซ่อนและลบล้างได้สำหรับเมธอดเท่านั้น กฎเดียวกันนี้ใช้ไม่ได้กับตัวแปร ไม่อนุญาตให้ลบล้างตัวแปรดังนั้นจึงสามารถซ่อนตัวแปรได้เท่านั้น (ไม่มีความแตกต่างระหว่างตัวแปรคงที่หรือไม่คงที่) ตัวอย่างด้านล่างแสดงวิธีการgetName()ลบล้างวิธีการและตัวแปรnameถูกซ่อนไว้:

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

ในรันไทม์เวอร์ชันลูกของเมธอดที่ถูกลบล้างจะถูกเรียกใช้สำหรับอินสแตนซ์เสมอไม่ว่าการเรียกเมธอดนั้นจะถูกกำหนดในเมธอดพาเรนต์หรือคลาสย่อย ในลักษณะนี้จะไม่มีการใช้เมธอดพาเรนต์เว้นแต่จะมีการอ้างถึงการเรียกอย่างชัดเจนไปยังเมธอดหลักโดยใช้ไวยากรณ์ ParentClassName.method () อีกวิธีหนึ่งที่รันไทม์เวอร์ชันพาเรนต์ของเมธอดที่ซ่อนอยู่จะถูกเรียกใช้เสมอหากการเรียกใช้เมธอดถูกกำหนดไว้ในคลาสพาเรนต์


0

ในการแทนที่เมธอดการแก้ปัญหาเมธอดจะกระทำโดย JVM บนพื้นฐานของอ็อบเจ็กต์รันไทม์ ในขณะที่การซ่อนเมธอดคอมไพเลอร์จะทำวิธีการแก้ปัญหาบนพื้นฐานของการอ้างอิง ด้วยประการฉะนี้

ถ้ารหัสจะถูกเขียนเป็น

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

ผลลัพธ์จะเป็นดังนี้:
วิธีการคลาสในสัตว์


0

เรียกว่าการซ่อนเนื่องจากคอมไพลเลอร์ซ่อนการนำเมธอดระดับซุปเปอร์คลาสไปใช้เมื่อคลาสย่อยมีเมธอดแบบคงที่เหมือนกัน

คอมไพลเลอร์ไม่มีการมองเห็นที่ จำกัด สำหรับเมธอดที่ถูกลบล้างและในระหว่างรันไทม์เท่านั้นที่จะตัดสินใจว่าจะใช้วิธีใด


0

นี่คือความแตกต่างระหว่างการลบล้างและการซ่อน:

สัตว์ a = แมวตัวใหม่ ();

a.testClassMethod () จะเรียกเมธอดในคลาสพาเรนต์เนื่องจากเป็นตัวอย่างของการซ่อนเมธอด วิธีการเรียกใช้จะพิจารณาจากชนิดของตัวแปรอ้างอิงและตัดสินใจในเวลาคอมไพล์

a.testInstanceMethod () จะเรียกเมธอดในคลาสลูกเนื่องจากเป็นตัวอย่างของการแทนที่เมธอด เมธอดที่จะเรียกถูกกำหนดโดยอ็อบเจ็กต์ซึ่งใช้เพื่อเรียกเมธอดในรันไทม์


0

ฉันคิดว่านี่ยังอธิบายไม่หมด โปรดดูตัวอย่างต่อไปนี้

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

ผลลัพธ์จะเป็นดังนี้

The static method in Animal
The static method in Cat
The instance method in Cat
The instance method in Cat

-1

วิธีการซ่อนวิธีคงที่เกิดขึ้นใน java ได้อย่างไร คลาสแมวกำลังขยายคลาสสัตว์ ดังนั้นในคลาส Cat จะมีทั้งวิธีแบบคงที่ (ฉันหมายถึงวิธีการแบบคงที่ของคลาสลูกและวิธีการคงที่ของคลาสแม่) แต่ JVM จะซ่อนเมธอด Parent static ได้อย่างไร วิธีการจัดการใน Heap และ Stack?


นี่ไม่ใช่คำตอบ เป็นส่วนขยายของคำถามที่ถาม อาจเป็นคำถามแยกต่างหากหรือเป็นส่วนหนึ่งของความคิดเห็นในคำถาม
Sri9911
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.