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

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

รหัสมีดังนี้:

ElectronicProduct eProduct = new ElectronicProduct();
eProduct.loadFromFile(eProduct,bin); 

อย่างไรก็ตาม มันเรียกใช้เมธอดในคลาสพาเรนต์ด้านล่าง:

public Product loadFromFile(Product aProduct, BufferedReader bin) throws IOException, ParseException{ 

   //some code 

}

แทนที่จะเป็นคลาสย่อยที่แสดงด้านล่าง:

public ElectronicProduct loadFromFile(Product aProduct, BufferedReader bin) throws IOException, ParseException{

// Some code

}

ฉันลองใช้ @Override ในเมธอดคลาสย่อย แต่เนื่องจากอันหนึ่งส่งคืนผลิตภัณฑ์และอีกอันส่งคืนผลิตภัณฑ์อิเล็กทรอนิกส์ ดูเหมือนว่าการแทนที่จะไม่ทำงาน ความช่วยเหลือใด ๆ ที่จะได้รับการชื่นชมอย่างมาก.

แก้ไข

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

แก้ไข*2

เพื่อตอบสนองต่อความคิดเห็นจาก Tiffado สาเหตุที่วัตถุ Product ถูกส่งเข้ามาและไม่ใช่วัตถุ ElectronicProduct นั้นเป็นเพราะภายในเมธอดคลาสลูกนั้น วัตถุ Product จะถูกส่งผ่านไปยังคลาสพาเรนต์ ถ้าฉันส่งออบเจ็กต์คลาสลูกไปยังวิธีลูกแทน จากนั้นส่งออบเจ็กต์ไปยังวิธีพาเรนต์แทน มันอาจไม่ได้ผล เนื่องจากฉันได้เรียนรู้ว่าคลาสพาเรนต์ไม่ 'เห็น' คลาสลูก โปรดแก้ไขฉันหากสิ่งนี้ไม่ถูกต้อง

public ElectronicProduct loadFromFile(Product aProduct, BufferedReader bin) throws IOException, ParseException{


ElectronicProduct eProduct = new ElectronicProduct();

eProduct = (ElectronicProduct)super.loadFromFile(aProduct,bin);

eProduct.setGuarunteeDuration(Integer.valueOf(bin.readLine()));

return eProduct;

}

person InitialisingAttributes    schedule 05.02.2020    source แหล่งที่มา
comment
วิธีการแทนที่ได้รับอนุญาตให้ส่งคืนประเภทที่เฉพาะเจาะจงมากขึ้น (ตั้งแต่ Java 5) เราไม่รู้ว่าคุณทำอะไรมาก่อน ดังนั้นเราจึงไม่สามารถพูดได้ว่าคุณทำอะไรผิด   -  person Holger    schedule 05.02.2020


คำตอบ (2)


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

วิธีการ:

public Product loadFromFile(Product aProduct, BufferedReader bin) throws IOException, ParseException{ 

เป็นเพียงเช่นเดียวกับ

public ElectronicProduct loadFromFile(Product aProduct, BufferedReader bin) throws IOException, ParseException{

เนื่องจากประเภทการส่งคืน (ElectronicProduct) เป็นคลาสย่อยของผลิตภัณฑ์ ดังนั้นจึงไม่ได้เป็นส่วนหนึ่งของลายเซ็นวิธีการใช้ความหลากหลาย

ดูเพิ่มเติม: "ลายเซ็นวิธี Java ใช้เฉพาะชื่อวิธี หมายเลข และประเภทของพารามิเตอร์" ดูได้ที่: https://docs.oracle.com/javase/tutorial/java/javaOO/methods.html

โปรดดูตัวอย่างถัดไป ซึ่งจะเรียกเมธอดลูกว่าด้วยการแทนที่กฎ แต่ เนื่องจากมีการเรียกฮาร์ดโค้ดไปยังพาเรนต์ มันจะเรียกเมธอดพาเรนต์ด้วย:

public class Product {

  static int productIdentifier = 0;
  static int electronicProductIdentifier = 0;

    public Product loadFromFile( Product aProduct ) {

    System.out.println("Call loadFromFile from Product");
        Product product = new Product();
        return product;

    }

  public Product ()  {
    System.out.println("Creating a Product with ID " + 
            ( ++ productIdentifier ) );
  }

}


public class ElectronicProduct extends Product {

    public ElectronicProduct loadFromFile( Product aProduct ) {

    System.out.println("Call loadFromFile from ElectronicProduct");
        ElectronicProduct eProduct = new ElectronicProduct();
    super.loadFromFile( eProduct ); // Hardcoded call to parent!
        return eProduct;

    }

  public ElectronicProduct ()  {
    System.out.println("Creating an ElectronicProduct with ID " + 
            ( ++ electronicProductIdentifier ) );
  }

}

Product p = new Product();
ElectronicProduct ep = new ElectronicProduct();
ep.loadFromFile( ep );

เอาท์พุท:

Creating a Product with ID 1
Creating a Product with ID 2
Creating an ElectronicProduct with ID 1
Call loadFromFile from ElectronicProduct
Creating a Product with ID 3
Creating an ElectronicProduct with ID 2
Call loadFromFile from Product
Creating a Product with ID 4

(มีการเรียก loadFromFile() จากผลิตภัณฑ์ เนื่องจากถูกเรียกอย่างชัดเจนจาก ElectronicProduct.loadFromFile() )

หากคุณแสดงความคิดเห็นในสายที่โทรไปที่ super.loadFromFile() คุณจะไม่เห็นสายที่โทรไปที่ Product.loadFromFile():

Creating a Product with ID 1
Creating a Product with ID 2
Creating an ElectronicProduct with ID 1
Call loadFromFile from ElectronicProduct
Creating a Product with ID 3
Creating an ElectronicProduct with ID 2
person Victor Polo De Gyves Montero    schedule 05.02.2020
comment
ขอบคุณสำหรับข้อมูลเชิงลึกนี้ ฉันคิดว่าคอมไพเลอร์จะเลือกวิธีคลาสย่อยโดยอัตโนมัติหากได้รับตัวเลือก สิ่งนี้ไม่ถูกต้องใช่ไหม? - person InitialisingAttributes; 05.02.2020
comment
คุณถูก. เนื่องจากนี่คือวิธีการแทนที่ มันจะเรียกคลาสย่อยเสมอ (วิธีการแทนที่อินสแตนซ์จะมีความสำคัญกว่า) ฉันมีคำถามโง่ๆ แต่คุณฮาร์ดโค้ดการเรียก super.loadFromFile() ภายใน ElectronicProduct ดังนั้นคุณจึงบังคับให้เรียกไปที่ Product.loadFromFile() ดังนั้นจึงถูกต้องที่คาดว่าจะเห็น Product.loadFromFile() ถูกเรียก จะแก้ไขคำตอบของฉันเพื่อให้คุณเป็นตัวอย่าง - person Victor Polo De Gyves Montero; 05.02.2020
comment
ฉันไม่คิดว่าจะถูกต้องที่เห็น Product.loadFromFile() ถูกเรียก แม้ว่าจะถูกฮาร์ดโค้ดลงใน ElectronicProduct.loadFromFile() ก็ตาม เนื่องจากพวกมันมีเนื้อความของวิธีการที่แตกต่างกัน และส่งคืนอ็อบเจ็กต์ที่แตกต่างกัน แต่อาจมีคนอื่นจำเป็นต้องยืนยันสิ่งนี้ - person InitialisingAttributes; 05.02.2020
comment
ประเภทการส่งคืนไม่ได้เป็นส่วนหนึ่งของลายเซ็นวิธีการ นี่คือสาเหตุที่นี่เป็นตัวอย่างของการแทนที่เมธอด และจะเรียกอินสแตนซ์เมธอดของ ElectronicProduct แทน Product เสมอ โปรดดู: docs.oracle.com/javase/tutorial/java/IandI/override.html - person Victor Polo De Gyves Montero; 05.02.2020

บางทีคุณควรใช้วิธีการเช่นนี้:

public ElectronicProduct loadFromFile(ElectronicProduct aProduct, BufferedReader bin) throws IOException, ParseException{

เนื่องจากความแตกต่างที่สำคัญคือออบเจ็กต์ที่คุณใส่ไว้ในพารามิเตอร์ คุณจึงควรระบุมัน

person Tiffado    schedule 05.02.2020
comment
ฉันได้แก้ไขคำถามแล้ว หากฉันส่งวัตถุลูกในอาจไม่ทำงานเนื่องจาก .super ใช้เพื่อส่งผ่านไปยังวิธีหลักซึ่งไม่สามารถ 'เห็น' วัตถุลูกได้ - person InitialisingAttributes; 05.02.2020