ประเภทผลตอบแทนโควาเรียนคืออะไร?


105

ประเภทผลตอบแทนโควาเรียนใน Java คืออะไร? ในการเขียนโปรแกรมเชิงวัตถุโดยทั่วไป?


5
โพสต์บล็อกนี้ ( blogs.oracle.com/sundararajan/entry/… ) อธิบายเพียงแค่เพิ่มฐานความรู้ที่นี่
Akhil Jain

@AkhilJain: บล็อกโพสต์นั้นยอดเยี่ยมและเรียบง่าย มันเป็นคำอธิบายทีละตัวอย่างที่ดีที่สุดที่ฉันเคยเห็นว่า Java สนับสนุนประเภทการส่งคืนโควาเรียนอย่างไร
kevinarpe

@kevinarpe ขอบคุณฉันดีใจที่มีประโยชน์กับหลาย ๆ คน
Akhil Jain

คำตอบ:


143

Covariant return หมายถึงเมื่อมีการแทนที่เมธอดประเภทการส่งคืนของวิธีการแทนที่จะได้รับอนุญาตให้เป็นประเภทย่อยของประเภทการส่งคืนของเมธอดที่ถูกแทนที่

เพื่อชี้แจงสิ่งนี้ด้วยตัวอย่างกรณีทั่วไปคือObject.clone()- ซึ่งถูกประกาศให้ส่งคืนประเภทของObject. คุณสามารถแทนที่สิ่งนี้ในชั้นเรียนของคุณเองได้ดังนี้:

public class MyFoo
{

   ...

   // Note covariant return here, method does not just return Object
   public MyFoo clone()
   {
       // Implementation
   }
}

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

โปรดทราบว่าไม่มีอะไรพิเศษเกี่ยวกับclone()วิธีการใด ๆ และวิธีการใด ๆ ที่ถูกลบล้างสามารถมีผลตอบแทนจากโควาเรียได้ - ฉันใช้เป็นตัวอย่างที่นี่เนื่องจากเป็นวิธีมาตรฐานที่มักเป็นประโยชน์


มันไม่ควรจะเกี่ยวข้องกับList<Foo>และList<FooBar>?
zinking

2
นั่นคือประเภทของโควาเรียในความหมายที่กว้างขึ้นแทนที่จะเป็นเพียงประเภทการกลับมาของโควาเรียที่ถามถึงที่นี่ มันเป็นหลักการพื้นฐานเดียวกัน - คุณสามารถนึกถึงคำจำกัดความระดับบนสุดของclone()การเป็น a Method<Void, Object>และถามว่ายิ่งเฉพาะเจาะจงมากขึ้นMethod<Void, MyFoo>สามารถกำหนดให้กับประเภทหลักนั้นได้หรือไม่ ซึ่งจะเป็นในกรณีที่เมธอด Java เป็นแบบ covariant ในประเภทการส่งคืนเท่านั้น
Andrzej Doyle

38

นี่เป็นอีกตัวอย่างง่ายๆ:

Animal ชั้นเรียน

public class Animal {

    protected Food seekFood() {

        return new Food();
    }
}

Dog ชั้นเรียน

public class Dog extends Animal {

    @Override
    protected Food seekFood() {

        return new DogFood();
    }
}

มันเป็นไปได้ที่จะปรับเปลี่ยนประเภทการกลับมาของDog's seekFood()วิธีการDogFood- คลาสย่อยของFoodที่แสดงด้านล่าง:

@Override
protected DogFood seekFood() {

    return new DogFood();
}

นั่นคืออย่างสมบูรณ์แบบที่เอาชนะกฎหมายและประเภทของการกลับมาของDog's seekFood()วิธีการเป็นที่รู้จักกันชนิดกลับ covariant


8

จากการเปิดตัว JDK 1.5 ประเภทของโควาเรียนถูกนำมาใช้ใน Java และฉันจะอธิบายให้คุณฟังเป็นกรณีง่ายๆ: เมื่อเราแทนที่ฟังก์ชันฟังก์ชันจะได้รับอนุญาตให้เปลี่ยนแปลงพฤติกรรมนั่นคือสิ่งที่คุณได้อ่านในหนังสือส่วนใหญ่ แต่สิ่งที่พวกเขา {ผู้เขียน} พลาดไป คือเราสามารถเปลี่ยนประเภทการคืนสินค้าได้ด้วย ตรวจสอบลิงก์ด้านล่างเพื่อดูคำชี้แจงเราสามารถเปลี่ยนประเภทการส่งคืนได้ตราบเท่าที่สามารถกำหนดให้ส่งคืนประเภทของวิธีการเวอร์ชันพื้นฐานได้

ดังนั้นคุณลักษณะของการส่งคืนประเภทที่ได้รับนี้จึงเรียกว่า COVARIANT ...

วิธีการแทนที่อาจแตกต่างกันในประเภทผลตอบแทนหรือไม่


7

ประเภทการส่งคืนโควาเรียนหมายถึงการส่งคืนการอ้างอิงคลาสของตัวเองหรือการอ้างอิงคลาสย่อย

class Parent {
 //it contain data member and data method
}

class Child extends Parent { 
//it contain data member and data method
 //covariant return
  public Parent methodName() {
     return new Parent();
          or 
     return Child();
  }

}

1
นอกจากนี้ยังมีกรณีที่Parent.foo()ส่งกลับที่ไม่เกี่ยวข้องกับชนิดAและChild.foo()ผลตอบแทนที่เป็นชนิดที่ได้มาจากB A
Davis Herring

2

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


1

ประเภทการส่งคืน Covariant ระบุว่าประเภทผลตอบแทนอาจแตกต่างกันไปในทิศทางเดียวกันกับคลาสย่อย

class One{  
    One get(){return this;}  
}  

class Two extends One{  
  Two get(){return this;}  

void message(){
  System.out.println("After Java5 welcome to covariant return type");
}  

public static void main(String args[]){  
    new Two().get().message();  
}  
}

ก่อน Java 5 จะไม่สามารถแทนที่เมธอดใด ๆ ได้โดยการเปลี่ยนประเภทการส่งคืน แต่ตอนนี้ตั้งแต่ Java5

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


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

  • ช่วยในการป้องกันการรันเวลา ClassCastExceptions ในการส่งคืน

อ้างอิง: www.geeksforgeeks.org


0
  • ประเภทการส่งคืน covariant ใน java อนุญาตให้ จำกัด ประเภทการส่งคืนของวิธีการที่ถูกแทนที่ให้แคบลง
  • คุณลักษณะนี้จะช่วยหลีกเลี่ยงการแคสต์จากฝั่งไคลเอ็นต์ ช่วยให้โปรแกรมเมอร์สามารถตั้งโปรแกรมได้โดยไม่จำเป็นต้องตรวจสอบประเภทและการหล่อ
  • ประเภทการส่งคืนโควาเรียนจะใช้ได้เฉพาะกับประเภทการส่งคืนที่ไม่ใช่แบบดั้งเดิมเท่านั้น
interface Interviewer {
    default Object submitInterviewStatus() {
        System.out.println("Interviewer:Accept");
        return "Interviewer:Accept";
    }
}
class Manager implements Interviewer {
    @Override
    public String submitInterviewStatus() {
        System.out.println("Manager:Accept");
        return "Manager:Accept";
    }
}
class Project {
    public static void main(String args[]) {
        Interviewer interviewer = new Manager();
        interviewer.submitInterviewStatus();
        Manager mgr = new Manager();
        mgr.submitInterviewStatus();
    }
}

ตัวอย่างอื่น ๆ มาจาก Java

UnaryOperator.java

@FunctionalInterface
public interface UnaryOperator<T> extends Function<T, T> {

    /**
     * Returns a unary operator that always returns its input argument.
     *
     * @param <T> the type of the input and output of the operator
     * @return a unary operator that always returns its input argument
     */
    static <T> UnaryOperator<T> identity() {
        return t -> t;
    }
}

Function.java

@FunctionalInterface
public interface Function<T, R> {

    ........
    ........
    ........
    ........

    static <T> Function<T, T> identity() {
        return t -> t;
    }
}

0

ก่อน Java5 ไม่สามารถแทนที่เมธอดใด ๆ โดยการเปลี่ยนชนิดการส่งคืน แต่ตอนนี้เนื่องจาก Java5 เป็นไปได้ที่จะแทนที่เมธอดโดยการเปลี่ยนประเภทการส่งคืนหากคลาสย่อยแทนที่เมธอดใด ๆ ที่ประเภทการส่งคืนเป็น Non-Primitive แต่จะเปลี่ยนประเภทการส่งคืนเป็นประเภทคลาสย่อย

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