คลาสย่อยสืบทอดฟิลด์ส่วนบุคคลหรือไม่


245

นี่คือคำถามสัมภาษณ์

คลาสย่อยสืบทอดฟิลด์ส่วนบุคคลหรือไม่

ฉันตอบว่า "ไม่" เพราะเราไม่สามารถเข้าถึงได้โดยใช้ "วิธี OOP ปกติ" แต่ผู้สัมภาษณ์คิดว่าพวกเขาได้รับมรดกเพราะเราสามารถเข้าถึงสาขาดังกล่าวทางอ้อมหรือใช้การสะท้อนและพวกเขายังคงอยู่ในวัตถุ

หลังจากฉันกลับมาฉันพบข้อความอ้างอิงต่อไปนี้ในjavadoc :

สมาชิกส่วนตัวใน Superclass

คลาสย่อยไม่สืบทอดสมาชิกส่วนตัวของคลาสพาเรนต์

คุณรู้ข้อโต้แย้งใด ๆ สำหรับความคิดเห็นของผู้สัมภาษณ์หรือไม่?


33
ฉันอยู่ในสถานการณ์ที่คล้ายคลึงกันครั้งหนึ่งและฉันก็รู้ว่าฉันไม่ต้องการทำงานให้ บริษัท ที่ผู้สัมภาษณ์รู้เรื่อง Java น้อยกว่าฉัน :)
biziclop

48
ผู้สัมภาษณ์บางครั้งจะไม่เห็นด้วยกับคุณแม้ว่าเขาจะรู้ว่าคุณพูดถูก ผู้สัมภาษณ์ที่ดีจะพยายามเรียนรู้เกี่ยวกับคุณมากกว่าความรู้ด้านเทคนิคของคุณ
Andy Thomas

4
@DigitalRoss สเปคภาษา Java ก็เขียนได้ไม่ดีเช่นกัน? ดู RD01 คำตอบ: stackoverflow.com/questions/4716040/…
OscarRyz

9
@ Andy Thomas-Cramer ฉันไม่อยากทำงานกับคนที่จงใจโกหกเพื่อทดสอบปฏิกิริยาของฉันเช่นกัน
biziclop

4
ฉันคิดว่าเราควรเข้าใจความหมายของ "การสืบทอด" ใน Java ก่อน คลาสย่อยไม่มีฟิลด์ไพรเวตและคลาสย่อยมีฟิลด์ไพรเวต แต่ไม่สามารถเข้าถึงได้แตกต่างกันซึ่งอันใดที่อ้างถึงความหมายที่แท้จริงของการสืบทอดใน Java?
MengT

คำตอบ:


238

ความสับสนส่วนใหญ่ในคำถาม / คำตอบที่นี่ล้อมรอบคำจำกัดความของการสืบทอด

เห็นได้ชัดว่า @DigitalRoss อธิบายOBJECTของคลาสย่อยจะต้องมีฟิลด์ส่วนตัวของซูเปอร์คลาส ในขณะที่เขากล่าวว่าการเข้าถึงสมาชิกส่วนตัวไม่ได้หมายความว่าไม่ได้อยู่ที่นั่น

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

ในฐานะรัฐ JLS ( https://docs.oracle.com/javase/specs/jls/se8/html/jls-8.html#jls-8.2 ):

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

คำถามนี้จะตอบคำถามที่ถูกต้องโดยผู้สัมภาษณ์: "ทำคลาสย่อยรับช่วงของฟิลด์ส่วนตัว" (เน้นโดยฉัน)

คำตอบคือไม่พวกเขาทำไม่ได้ OBJECTS ของคลาสย่อยมีฟิลด์ส่วนตัวของซูเปอร์คลาส คลาสย่อยเองนั้นมีแนวคิดของฟิลด์ส่วนตัวของซูเปอร์คลาส

มันเป็นความหมายของธรรมชาติอวดความรู้? ใช่. มันเป็นคำถามสัมภาษณ์ที่มีประโยชน์หรือไม่? อาจจะไม่. แต่ JLS สร้างคำจำกัดความสำหรับโลกของ Java และในกรณีนี้ (ในกรณีนี้) นั้นไม่คลุมเครือ

แก้ไข (ลบอัญประกาศคู่ขนานจาก Bjarne Stroustrup ซึ่งเนื่องจากความแตกต่างระหว่าง java และ c ++ อาจเพิ่มความสับสนเท่านั้นฉันจะให้คำตอบของฉันวางอยู่บน JLS :)


3
@ ดิจิทัลทำไมถอนหายใจ ฉันเข้าใจว่าคุณเชื่อว่าคุณพูดถูก ฉันไม่เห็นด้วยกับคุณว่าการสืบทอดวัตถุเป็นสิ่งที่โปรแกรมเมอร์ส่วนใหญ่สอน / คิด แต่คำจำกัดความของ JLS จะนำไปใช้กับคำถามเดิมโดยตรง มันเป็นความหมายใช่ แต่ JLS กำหนดคำจำกัดความไม่ใช่คุณหรือ I.
robert_x44

4
วิธีหนึ่งในการกระทบยอดทั้งหมดนี้คือการรับรู้ว่าคำว่า"การสืบทอด"ใช้ในสองวิธีที่แตกต่างกันมากในการอธิบายความสัมพันธ์ของคลาสที่ได้รับและผู้ปกครองอย่างน้อยในโลก Java ใช่ JSL มีสิทธิ์ ใช่มันหมายความว่าคุณสามารถใช้ "รับช่วง" ในทางที่โชคร้าย แต่ก็ยังคงเป็นความจริงที่ชัดเจนว่า subclasses froggle (เพราะตอนนี้เราไม่มีคำศัพท์) ฟิลด์ส่วนตัวของคลาสผู้ปกครอง
DigitalRoss

1
@digital พวกเขาอยู่ในวัตถุของชั้นเรียน ไม่ใช่ชั้นเรียน Simula เรียกมันว่าวัตถุที่ต่อกัน เมื่อวัตถุของคลาสย่อยถูกสร้างขึ้นมันถูกสร้างขึ้นจาก 'คำนำหน้าวัตถุ' เรียงต่อกัน วัตถุ superclass เป็นวัตถุคำนำหน้าที่ตัวเองอาจมีวัตถุคำนำหน้าอื่น ๆ ฉันคิดว่ามันหยิ่งที่จะพูดว่า JLS มี "ถ้อยคำที่ไม่ดีอย่างชัดเจน" สำหรับสิ่งที่เราใช้คำว่าสืบทอดแน่นอน ไม่มีอะไรผิดปกติกับการใช้คำศัพท์ที่ไม่ชัดเจนเล็กน้อย มันเกิดขึ้นตลอดเวลา แต่นั่นไม่ได้หมายความว่าไม่มีคำจำกัดความที่แม่นยำ
robert_x44

1
@digital เราสามารถตกลงกันได้อย่างแน่นอนว่าคำนั้นถูกใช้ในวิธีที่ต่างกัน :) เราอาจเห็นด้วยว่าคำถามสัมภาษณ์ที่ขึ้นอยู่กับคำที่คลุมเครือนั้นอาจไม่ใช่คำถามที่ดี
robert_x44

2
ใครมีการอ้างอิงจาก Java / Oracle สำหรับ "วัตถุของคลาสย่อยมีเขตข้อมูลส่วนตัวของซูเปอร์คลาส" ฉันเห็นด้วยกับสิ่งนี้ แต่ไม่สามารถหาเอกสารทางการใด ๆ ที่บอกว่า
MengT

78

ใช่

มันเป็นสิ่งสำคัญที่จะตระหนักว่าในขณะที่มีมีสองชั้นมีเพียงหนึ่งวัตถุ

ใช่แน่นอนมันได้รับมรดกมาจากภาคเอกชน สันนิษฐานว่าเป็นสิ่งจำเป็นสำหรับการทำงานของวัตถุที่เหมาะสมและในขณะที่วัตถุของคลาสแม่ไม่ได้เป็นวัตถุของคลาสที่ได้รับอินสแตนซ์ของคลาสที่ได้รับนั้นส่วนใหญ่จะเป็นตัวอย่างของคลาสพาเรนต์ มันเป็นไปไม่ได้เลยหากไม่มีทุกสาขา

ไม่คุณไม่สามารถเข้าถึงได้โดยตรง ใช่พวกเขาได้รับมรดก พวกเขามีที่จะเป็น

มันเป็นคำถามที่ดี!


ปรับปรุง:

ผิดพลาด "ไม่"

ฉันเดาว่าเราทุกคนเรียนรู้อะไรบางอย่าง ตั้งแต่JLSเกิดขึ้นแน่นอน "ไม่ได้รับการสืบทอด" ถ้อยคำที่มันเป็นเรื่องที่ถูกต้องที่จะตอบว่า "ไม่" เนื่องจากคลาสย่อยไม่สามารถเข้าถึงหรือแก้ไขฟิลด์ส่วนตัวดังนั้นจึงไม่ได้รับมรดก แต่มีจริงๆเป็นเพียงแค่หนึ่งในวัตถุจริงๆมันไม่ประกอบด้วยเขตข้อมูลส่วนตัวและดังนั้นหากใครเตะ JLS และถ้อยคำกวดวิชาทางที่ผิดก็จะเป็นเรื่องยากมากที่จะเข้าใจ OOP, Java วัตถุและสิ่งที่เป็นจริงที่เกิดขึ้น

อัปเดตเพื่ออัปเดต:

การโต้เถียงที่นี่เกี่ยวข้องกับความกำกวมพื้นฐาน: อะไรคือสิ่งที่ถูกกล่าวถึง? วัตถุ? หรือเรากำลังพูดถึงความรู้สึกบางอย่างเกี่ยวกับชั้นเรียนของตัวเอง? ละติจูดจำนวนมากได้รับอนุญาตเมื่ออธิบายคลาสเมื่อเทียบกับวัตถุ ดังนั้นคลาสย่อยจะไม่สืบทอดฟิลด์ส่วนตัว แต่วัตถุที่เป็นตัวอย่างของคลาสย่อยนั้นจะมีฟิลด์ส่วนตัวอย่างแน่นอน


2
@ Ma99uS แน่นอนว่าพวกเขาจะถูกนำมาใช้ซ้ำ นั่นคือจุดทั้งหมดของการสืบทอด หากไม่มีพวกเขาประเภทที่ได้รับจะไม่และไม่สามารถเป็นตัวอย่างของประเภทผู้ปกครอง OOP คงไม่มีความหมาย ประเภท polymorphic จะหยุดทำงาน การเข้าใจว่ามีเพียงวัตถุเดียวและคุณเป็นตัวอย่างของประเภทผู้ปกครองนั้นเป็นสิ่งสำคัญในการทำความเข้าใจ OOP คุณต้องผ่านพ้นปัญหานี้เพื่อเข้าใจมันทั้งหมด
DigitalRoss

2
ไม่แน่ใจว่าตัวอย่างพ่อดีมากเพราะสามารถรับมรดกได้ในขณะที่ผู้ปกครองยังมีชีวิตอยู่และมีฟิลด์นั้น หากการรับมรดกทำงานเช่นนั้นฉันก็สามารถสืบทอดเงินของพ่อฉันในขณะที่เขายังมีชีวิตอยู่และเขาสามารถเก็บเงินไว้เหมือนกันได้ ลูก ๆ ของฉันต่างก็มีเงินและเงินของเขา
Peter Lawrey

2
@ Peter Lawrey ไม่เถียงหรืออะไร แต่นี่คือสิ่งที่ฉันคิด ผู้ปกครองมีcarเขาเก็บไว้ในprivateตู้เก็บของที่เด็กไม่ได้เป็นกุญแจของ คุณได้รับมรดกแน่นอนcarแต่มันไร้ประโยชน์สำหรับคุณ ดังนั้นในทางปฏิบัติคุณไม่ได้รับประโยชน์จากการสืบทอด
Nishant

1
@DigitalRoss ฉันเข้าใจประเด็นของคุณ Mhh เราสามารถพูดได้ว่าค่านั้นอยู่ที่นั่นเพราะมีการโหลดคำจำกัดความของผู้ปกครองที่ไม่สืบทอดมา :) ฉันคิดว่าข้อมูลจำเพาะของ JVM จะมีคำตอบที่ถูกต้องสำหรับคำว่า "ไม่มีคำว่า" ที่เรากำลังมองหา java.sun.com/docs/books/jvms
OscarRyz

5
-1, ข้อกำหนดภาษา Java ชัดเจนว่าพวกเขาไม่ได้รับมรดก ไม่ว่าจะเป็นแค่ไม่มี พวกเขาไม่เพียง นิยามการสืบทอดอื่น ๆ นั้นผิดในบริบทของ Java
biziclop

21

ไม่ฟิลด์ส่วนตัวไม่ได้รับการสืบทอด ... และนั่นเป็นสาเหตุที่มีการป้องกันการคิดค้น มันเป็นโดยการออกแบบ ฉันเดาว่าสิ่งนี้มีเหตุผลที่จะมีการแก้ไขตัวป้องกัน


ตอนนี้มาถึงบริบท คุณหมายถึงอะไรโดยการสืบทอด - ถ้ามันมีอยู่ในวัตถุที่สร้างจากคลาสที่ได้รับ? ใช่แล้ว.

ถ้าคุณหมายถึงมันจะมีประโยชน์กับคลาสที่ได้รับมา ไม่เลย

ตอนนี้เมื่อคุณมาถึงโปรแกรมการทำงานสนามของเอกชนชั้นซุปเปอร์ไม่ได้รับมรดกในทางที่มีความหมายสำหรับประเภทรอง สำหรับคลาสย่อยฟิลด์ส่วนตัวของซูเปอร์คลาสนั้นเหมือนกับฟิลด์ส่วนตัวของคลาสอื่น ๆ

หน้าที่มันไม่ได้สืบทอด แต่ความนึกคิดมันคือ


ตกลงเพียงแค่มองเข้าไปในการกวดวิชา Java พวกเขาพูดแบบนี้:

สมาชิกส่วนตัวใน Superclass

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

อ้างอิง: http://download.oracle.com/javase/tutorial/java/IandI/subclasses.html

ฉันเห็นด้วยว่าทุ่งนาอยู่ที่นั่น แต่คลาสย่อยไม่ได้รับสิทธิพิเศษใด ๆ ในฟิลด์ส่วนตัวนั้น สำหรับคลาสย่อยฟิลด์ไพรเวตจะเหมือนกับฟิลด์ส่วนตัวของคลาสอื่น

ฉันเชื่อว่ามันเป็นเรื่องของมุมมอง คุณอาจสร้างข้อโต้แย้งทั้งสองด้าน มันจะแสดงเหตุผลที่ดีกว่าทั้งสองวิธี

 


2
สิ่งนี้ไม่ถูกต้อง คุณไม่สามารถเข้าถึงพวกเขานั่นถูกต้อง แต่พวกเขามีจะได้รับมรดกที่ผมได้อธิบาย
DigitalRoss

1
คำตอบที่ยอดเยี่ยม !!! +1 สำหรับI believe it's purely matter of point-of-view.และjustified the existence of protected modifier.
Ravi

14

ขึ้นอยู่กับคำจำกัดความของคุณของ "การสืบทอด" คลาสย่อยยังมีฟิลด์ในหน่วยความจำหรือไม่? อย่างแน่นอน. สามารถเข้าถึงได้โดยตรงหรือไม่ ไม่มันเป็นเพียงคำจำกัดความอย่างละเอียด จุดคือการเข้าใจสิ่งที่เกิดขึ้นจริง


แก้ไข. แต่ผมคิดว่าในคำถามฐานดังกล่าวควรจะมีคำตอบที่พบบ่อย)
สแตน Kurilin

ฉันคิดว่ามันเป็นนิยามของการสืบทอด Java
OscarRyz

มิฉะนั้นจะขึ้นอยู่กับคำจำกัดความของคุณ "ฟิลด์" ในการกำหนดเขตข้อมูลจำนวนเต็ม "foo" คือการให้เช่าตู้เก็บของขนาดเต็มและใส่เครื่องหมาย "foo" ลงไป ถ้าฟิลด์ถูกประกาศเป็นส่วนตัวคลาสที่ได้รับจะสืบทอดล็อกเกอร์เก็บข้อมูลขนาดเต็มจำนวนที่ไม่มีป้ายกำกับ คลาสที่ได้รับนั้นจะรับช่วง "field" หรือไม่นั้นขึ้นอยู่กับว่ามีการเรียกหนึ่งรายการที่ไม่ได้ติดฉลากตู้เก็บของแบบ "ฟิลด์" หรือไม่
supercat

10

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

พิจารณาสองคลาสในแพ็คเกจ Dump เด็กขยายผู้ปกครอง

ถ้าฉันจำอย่างถูกต้องวัตถุลูกในหน่วยความจำประกอบด้วยสองภูมิภาค หนึ่งคือส่วนหลักเท่านั้นและอื่น ๆ เป็นส่วนเด็กเท่านั้น เด็กสามารถเข้าถึงส่วนส่วนตัวในรหัสของผู้ปกครองเท่านั้นผ่านวิธีสาธารณะในผู้ปกครอง

คิดแบบนี้ พ่อของโบรตโบลอคมีตู้นิรภัยที่มีเงิน 100,000 เหรียญ เขาไม่ต้องการแบ่งปันตัวแปร "ส่วนตัว" ที่ปลอดภัย ดังนั้นเขาไม่ได้ให้กุญแจเพื่อความปลอดภัย Borat สืบทอดความปลอดภัย แต่มันจะดีอะไรถ้าเขาไม่สามารถเปิดมันได้? หากพ่อของเขาให้กุญแจ

ผู้ปกครอง -

package Dump;

public class Parent {

    private String reallyHidden;
    private String notReallyHidden;

    public String getNotReallyHidden() {
        return notReallyHidden;
    }

    public void setNotReallyHidden(String notReallyHidden) {
        this.notReallyHidden = notReallyHidden;
    }

}//Parent

เด็ก -

package Dump;

public class Child extends Parent {

    private String childOnly;

    public String getChildOnly() {
        return childOnly;
    }

    public void setChildOnly(String childOnly) {
        this.childOnly = childOnly;
    }

    public static void main(String [] args){

        System.out.println("Testing...");
        Child c1 = new Child();
        c1.setChildOnly("childOnly");
        c1.setNotReallyHidden("notReallyHidden");

        //Attempting to access parent's reallyHidden
            c1.reallyHidden;//Does not even compile

    }//main

}//Child

10

ไม่พวกมันไม่ได้รับมรดก

ความจริงบางคลาสอื่นอาจใช้โดยทางอ้อมไม่ได้พูดอะไรเกี่ยวกับการสืบทอด แต่เกี่ยวกับการห่อหุ้ม

ตัวอย่างเช่น

class Some { 
   private int count; 
   public void increment() { 
      count++;
   }
   public String toString() { 
       return Integer.toString( count );
   }
}

class UseIt { 
    void useIt() { 
        Some s = new Some();
        s.increment();
        s.increment();
        s.increment();
        int v = Integer.parseInt( s.toString() );
        // hey, can you say you inherit it?
     }
}

นอกจากนี้คุณยังสามารถรับค่าจากcountภายในUseItผ่านการสะท้อนกลับ มันไม่ได้หมายความว่าคุณจะสืบทอดมัน

UPDATE

แม้ว่าค่าจะอยู่ที่นั่น แต่ไม่ได้สืบทอดโดยคลาสย่อย

ตัวอย่างเช่นคลาสย่อยที่นิยามเป็น:

class SomeOther extends Some { 
    private int count = 1000;
    @Override
    public void increment() { 
        super.increment();
        count *= 10000;
    }
}

class UseIt { 
    public static void main( String ... args ) { 
        s = new SomeOther();
        s.increment();
        s.increment();
        s.increment();
        v = Integer.parseInt( s.toString() );
        // what is the value of v?           
     }
}

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

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

การปรับปรุงอื่น ๆ

มันเป็นเรื่องที่น่าสนใจมากหากต้องการทราบว่าเหตุใดจึงมีแอตทริบิวต์

ฉันตรงไปตรงมาไม่มีคำที่แน่นอนที่จะอธิบาย แต่เป็น JVM และวิธีการทำงานที่โหลดยังนิยามผู้ปกครอง "ไม่สืบทอด"

เราสามารถเปลี่ยนพาเรนต์และคลาสย่อยจะยังคงทำงานได้

ตัวอย่างเช่น :

//A.java
class A {
   private int i;
   public String toString() { return ""+ i; }
}
// B.java
class B extends A {}
// Main.java
class Main {
   public static void main( String [] args ) {
      System.out.println( new B().toString() );
    }
}
// Compile all the files
javac A.java B.java Main.java
// Run Main
java Main
// Outout is 0 as expected as B is using the A 'toString' definition
0

// Change A.java
class A {
   public String toString() {
      return "Nothing here";
   }
}
// Recompile ONLY A.java
javac A.java
java Main
// B wasn't modified and yet it shows a different behaviour, this is not due to 
// inheritance but the way Java loads the class
Output: Nothing here

ฉันเดาคำศัพท์ที่แน่นอนได้ที่นี่: ข้อมูลจำเพาะ JavaTM Virtual Machine


:) ครั้งต่อไปคุณอาจใช้โอกาสอธิบายผู้สัมภาษณ์ของคุณว่าเขา / เธอผิดตรงไหนและนี่อาจให้คะแนนพิเศษแก่คุณ) เห็นได้ชัดว่าคุณควรทำอย่างถูกวิธีทางการทูต
OscarRyz

1
พวกเขาได้จะได้รับมรดกชนิด polymorphic จะมีความหมายใด ๆ เลย ดูคำอธิบายของฉัน เป็นความจริงที่คุณไม่สามารถเล่นกับพวกมันได้ แต่พวกมันอยู่ที่นั่น พวกเขามีที่จะเป็น
DigitalRoss

ไม่มีคำสำคัญที่สืบทอด (ขยาย / นำไปปฏิบัติ) ในรหัสของคุณดังนั้นจึงไม่ใช่ตัวอย่างการสืบทอด
fmucar

1
เอ่อถ้าพวกเขาอยู่ที่นั่นพวกเขาไปถึงที่นั่นได้อย่างไร เนื่องจากคลาสย่อยกำหนดไว้หรือไม่ ไม่ได้เนื่องจากพวกเขาเอ่ออืมผิดพลาด, มรดกที่ได้รับ ?
DigitalRoss

1
จุดที่ดีในการencapsulationvs inheritฉันเดาคำตอบนี้สมควรได้รับการโหวตมากขึ้น
Eric Wang เมื่อ

6

คำตอบสำหรับคำถามของผู้สัมภาษณ์คือ - สมาชิกส่วนตัวไม่ได้รับการสืบทอดในคลาสย่อย แต่พวกเขาสามารถเข้าถึงออบเจ็กต์คลาสย่อยหรือคลาสย่อยได้เฉพาะผ่านวิธีการทะเยอทะยานสาธารณะหรือผู้ตั้งค่าหรือวิธีการอื่นใด การปฏิบัติปกติคือการทำให้สมาชิกเป็นส่วนตัวและเข้าถึงพวกเขาโดยใช้วิธี getter และ setter ซึ่งเป็นสาธารณะ ดังนั้นจุดเฉพาะในการสืบทอด getter และ setter วิธีเมื่อสมาชิกส่วนตัวที่พวกเขาจัดการกับวัตถุไม่สามารถใช้ได้? นี่คือ 'สืบทอด' เพียงหมายความว่ามันมีอยู่ในคลาสย่อยโดยตรงเพื่อเล่นโดยวิธีการที่แนะนำใหม่ในคลาสย่อย

บันทึกไฟล์ด้านล่างเป็น ParentClass.java และลองด้วยตัวคุณเอง ->

public class ParentClass {
  private int x;

  public int getX() {
    return x;
  }

  public void setX(int x) {
    this.x = x;
  }
}

class SubClass extends ParentClass {
  private int y;

  public int getY() {
    return y;
  }

  public void setY(int y) {
    this.y = y;
  }

  public void setXofParent(int x) {
    setX(x); 
  }
}

class Main {
  public static void main(String[] args) {
    SubClass s = new SubClass();
    s.setX(10);
    s.setY(12);
    System.out.println("X is :"+s.getX());
    System.out.println("Y is :"+s.getY());
    s.setXofParent(13);
    System.out.println("Now X is :"+s.getX());
  }
}

Output:
X is :10
Y is :12
Now X is :13

หากเราพยายามใช้ตัวแปรส่วนตัว x ของ ParentClass ในวิธีการของ SubClass มันจะไม่สามารถเข้าถึงได้โดยตรงสำหรับการแก้ไขใด ๆ (หมายถึงไม่สืบทอด) แต่ x สามารถแก้ไขได้ใน SubClass ผ่านวิธี setX () ของคลาสดั้งเดิมเช่นเดียวกับที่ทำในเมธอด setXofParent () หรือสามารถแก้ไขได้โดยใช้อ็อบเจ็กต์ ChildClass โดยใช้เมธอด setX () หรือเมธอด setXofParent () ซึ่งเรียกว่า setX () ดังนั้นที่นี่ setX () และ getX () เป็นชนิดของประตูสู่สมาชิกส่วนตัว x ของ ParentClass

อีกตัวอย่างง่ายๆคือ Clock superclass มีชั่วโมงและนาทีในฐานะสมาชิกส่วนตัวและวิธีการ getter และ setter ที่เหมาะสมเป็นสาธารณะ จากนั้น DigitalClock จะมาพร้อมกับนาฬิกาย่อย ที่นี่ถ้าวัตถุของ DigitalClock ไม่มีเวลาและสมาชิกนาทีสิ่งต่างๆจะถูกทำให้เมา


2
ตามเอกสารของ Oracle - คลาสย่อยไม่สืบทอดสมาชิกส่วนตัวของคลาสพาเรนต์ อย่างไรก็ตามหากซูเปอร์คลาสมีวิธีพับลิกหรือสาธารณะสำหรับการเข้าถึงฟิลด์ส่วนตัวของคลาสย่อยเหล่านี้ยังสามารถใช้งานได้
dganesh2002

4

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

import java.io.Serializable;
public class ParentClass implements Serializable {
public ParentClass() {

}

public int a=32131,b,c;

private int bhavesh=5555,rr,weq,refw;
}

import java.io.*;
import java.io.Serializable;
public class ChildClass extends ParentClass{
public ChildClass() {
super();
}

public static void main(String[] args) {
ChildClass childObj = new ChildClass();
ObjectOutputStream oos;
try {
        oos = new ObjectOutputStream(new FileOutputStream("C:\\MyData1.txt"));
        oos.writeObject(childObj); //Writing child class object and not parent class object
        System.out.println("Writing complete !");
    } catch (IOException e) {
    }


}
}

เปิด MyData1.txt และค้นหาสมาชิกส่วนตัวที่ชื่อว่า 'bhavesh' โปรดแจ้งให้เราทราบว่าคุณคิดอย่างไร


3

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

PS หนึ่งในคำจำกัดความจำนวนมากของการสืบทอดที่ฉันได้พบ: "การสืบทอด - เทคนิคการเขียนโปรแกรมที่อนุญาตให้คลาสที่ได้รับเพื่อขยายฟังก์ชันการทำงานของคลาสฐานการสืบทอดสถานะทั้งหมด (เน้นเป็นของฉัน) และพฤติกรรม"

ฟิลด์ส่วนบุคคลแม้ว่าจะไม่สามารถเข้าถึงได้โดยคลาสย่อยนั้นเป็นสถานะที่สืบทอดของซูเปอร์คลาส


1

ฉันจะต้องตอบว่าช่องส่วนตัวใน Java ได้รับมรดก อนุญาตให้ฉันสาธิต:

public class Foo {

    private int x; // This is the private field.

    public Foo() {
        x = 0; // Sets int x to 0.
    }

    //The following methods are declared "final" so that they can't be overridden.
    public final void update() { x++; } // Increments x by 1.
    public final int getX() { return x; } // Returns the x value.

}


public class Bar extends Foo {

    public Bar() {

        super(); // Because this extends a class with a constructor, it is required to run before anything else.

        update(); //Runs the inherited update() method twice
        update();
        System.out.println(getX()); // Prints the inherited "x" int.

    }

}

หากคุณทำงานในโปรแกรมBar bar = new Bar();จากนั้นคุณจะเห็นตัวเลข "2" เสมอในกล่องผลลัพธ์ เนื่องจากจำนวนเต็ม "x" ถูกห่อหุ้มด้วยเมธอดupdate()และgetX()จากนั้นจึงสามารถพิสูจน์ได้ว่าจำนวนเต็มที่สืบทอดมา

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


3
"มี" ไม่ได้หมายถึง "สืบทอด";)
Stan Kurilin

1

เค้าโครงหน่วยความจำในการสืบทอด Java vis-a-vis

ป้อนคำอธิบายรูปภาพที่นี่

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


1

ไม่ฟิลด์ส่วนตัวไม่ได้รับการถ่ายทอด เหตุผลเดียวก็คือว่า subclass ไม่สามารถเข้าถึงได้โดยตรง


0

ฉันเชื่อว่าคำตอบนั้นขึ้นอยู่กับคำถามซึ่งถูกถาม ฉันหมายถึงถ้าคำถามคือ

เราสามารถเข้าถึงฟิลด์ส่วนตัวของซูเปอร์คลาสโดยตรงจากคลาสย่อยได้หรือไม่?

ดังนั้นคำตอบคือไม่ถ้าเราไปถึงรายละเอียดตัวระบุการเข้าถึงจะมีการกล่าวถึงสมาชิกส่วนตัวสามารถเข้าถึงได้เฉพาะภายในชั้นเรียนเท่านั้น

แต่ถ้าคำถามคือ

เราสามารถเข้าถึงฟิลด์ส่วนตัวของซูเปอร์คลาสจากคลาสย่อยได้หรือไม่?

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

ภาษา OOP อื่น ๆ เช่น C ++ มีfriend functionแนวคิดซึ่งเราสามารถเข้าถึงสมาชิกส่วนตัวของคลาสอื่นได้


0

เราสามารถกล่าวง่ายๆว่าเมื่อซูเปอร์คลาสนั้นได้รับการสืบทอดสมาชิกส่วนตัวของซูเปอร์คลาสนั้นจะกลายเป็นสมาชิกส่วนตัวของคลาสย่อยและไม่สามารถสืบทอดต่อไปหรือไม่สามารถรับกับวัตถุของคลาสย่อยได้


0

สมาชิกคลาสหรือคอนสตรัคเตอร์ส่วนตัวสามารถเข้าถึงได้เฉพาะภายในเนื้อความของคลาสระดับบนสุด ( §7.6 ) ที่ล้อมรอบการประกาศของสมาชิกหรือคอนสตรัคเตอร์ ไม่ได้รับการสืบทอดโดยคลาสย่อย https://docs.oracle.com/javase/specs/jls/se7/html/jls-6.html#jls-6.6


-1

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


-2

สมาชิกส่วนตัว (สถานะและพฤติกรรม) ได้รับการสืบทอด พวกเขา (สามารถ) ส่งผลกระทบต่อพฤติกรรมและขนาดของวัตถุที่เป็นอินสแตนซ์โดยชั้นเรียน ไม่ต้องพูดถึงว่าพวกมันสามารถมองเห็น subclasses ได้อย่างดีผ่านกลไกการแตกหักแบบ encaptulation ทั้งหมดที่มีอยู่หรือสามารถถูกสันนิษฐานได้โดยผู้พัฒนาระบบ

แม้ว่าการสืบทอดจะมีคำจำกัดความ "defacto" แต่ก็ไม่มีการเชื่อมโยงไปยังแง่มุม "การมองเห็น" อย่างแน่นอน

ดังนั้นไม่จำเป็นต้องมีชั้นเชิง JLS ผิดพลาดในตอนนี้

การสันนิษฐานว่าพวกเขาไม่ใช่ "การสืบทอด" ใด ๆ นั้นไม่ปลอดภัยและอันตราย

ดังนั้นในคำจำกัดความที่ขัดแย้งกันสองข้อ (บางส่วน) (ซึ่งฉันจะไม่ทำซ้ำ) คำเดียวที่ควรปฏิบัติตามคือคำที่ปลอดภัย (หรือปลอดภัย)


1
-1 JLS กำหนดภาษาเป็นไปไม่ได้ที่ JLS จะ "ผิด" นอกจากนี้หากมีกลไกที่ทำลายการห่อหุ้มนั่นไม่ได้หมายความว่าจะได้รับมรดก เพียง แต่มีกลไกที่ล้มล้างการห่อหุ้ม
SL Barth - Reinstate Monica

คำจำกัดความสามารถผิดได้หลายประการ การพูดคุยเพิ่มเติมเกี่ยวกับเรื่องนี้ไม่ใช่ความตั้งใจของฉัน การโต้เถียงที่นี่ไม่ได้อยู่ในกลไกที่ทำลายการห่อหุ้ม (พระเจ้าหรือไม่ดีอย่างที่ควรจะเป็น) แต่โดยข้อเท็จจริงแล้วมีฟิลด์ / วิธีการอยู่ที่นั่นส่งผลกระทบต่อพฤติกรรมและสถานะของคลาสย่อยของคุณ ดังนั้นจึงเป็น "สืบทอด" หนึ่งสามารถใช้อาร์เรย์ไบต์ขนาดส่วนตัว 100kb ในคลาสและเพียงแค่สมมติว่าลูกหลานของเขา (จัมโบ้) ไม่ได้รับมรดก อย่าพลาดประเด็นและตัดสินสิ่งนี้ว่าเป็นการปฏิบัติที่ดีหรือไม่ดี (การพูดเกินจริงช่วยชี้ประเด็น): เป็นการคาดการณ์ล่วงหน้าที่ถูกต้องตามกฎหมาย สมาชิกส่วนตัวคือ "สืบทอด"
gkakas
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.