Kiểu trả về hiệp phương sai là gì?


105

Kiểu trả về hiệp phương sai trong Java là gì? Trong lập trình hướng đối tượng nói chung?


5
bài đăng trên blog này ( blog.oracle.com/sundararajan/entry/… ) giải thích, chỉ bổ sung vào cơ sở kiến ​​thức ở đây.
Akhil Jain

@AkhilJain: Bài đăng trên blog đó thật tuyệt và đơn giản. Đây là cách giải thích từng ví dụ tốt nhất mà tôi từng thấy về cách Java hỗ trợ các kiểu trả về hiệp phương sai.
kevinarpe

@kevinarpe cảm ơn, tôi rất vui vì nó hữu ích cho rất nhiều người.
Akhil Jain

Câu trả lời:


143

Trả về đồng biến, có nghĩa là khi người ta ghi đè một phương thức, kiểu trả về của phương thức ghi đè được phép trở thành một kiểu con của kiểu trả về của phương thức bị ghi đè.

Để làm rõ điều này với một ví dụ, một trường hợp phổ biến là Object.clone()- được khai báo để trả về một kiểu Object. Bạn có thể ghi đè điều này trong lớp của riêng mình như sau:

public class MyFoo
{

   ...

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

Lợi ích ở đây là bất kỳ phương thức nào chứa một tham chiếu rõ ràng đến một đối tượng MyFoo sẽ có thể gọi clone()và biết (không cần ép kiểu ) rằng giá trị trả về là một thể hiện của nó MyFoo. Nếu không có kiểu trả về hiệp biến, phương thức bị ghi đè trong MyFoo sẽ phải được khai báo để trả về Object- và do đó mã gọi sẽ phải truyền tải rõ ràng kết quả của lệnh gọi phương thức (thậm chí cả hai bên đều "biết" nó chỉ có thể là một phiên bản của MyFoo ).

Lưu ý rằng không có gì đặc biệt clone()và bất kỳ phương thức nào bị ghi đè đều có thể có trả về hiệp phương sai - tôi đã sử dụng nó làm ví dụ ở đây vì đây là một phương thức chuẩn, nơi điều này thường hữu ích.


nó không được cho là có liên quan với List<Foo>List<FooBar>?
zinking

2
Đó là các kiểu hiệp phương sai theo nghĩa rộng hơn là chỉ kiểu trả về hiệp phương sai được hỏi ở đây. Tuy nhiên, đó là nguyên tắc cơ bản giống nhau - bạn có thể nghĩ về định nghĩa cấp cao nhất clone()là trở thành a Method<Void, Object>và hỏi xem liệu cụ thể hơn có thể Method<Void, MyFoo>gán cho kiểu mẹ đó hay không. Đó là, nếu và chỉ khi các phương thức Java là hiệp biến trong kiểu trả về của chúng.
Andrzej Doyle

38

Đây là một ví dụ đơn giản khác:

Animal lớp học

public class Animal {

    protected Food seekFood() {

        return new Food();
    }
}

Dog lớp học

public class Dog extends Animal {

    @Override
    protected Food seekFood() {

        return new DogFood();
    }
}

Có thể sửa đổi kiểu trả về của phương thức Dog'thành - một lớp con của , như được hiển thị bên dưới:seekFood()DogFoodFood

@Override
protected DogFood seekFood() {

    return new DogFood();
}

Đó là một cách hoàn hảo một trọng pháp luật, và các kiểu trả về của Dog's seekFood()phương pháp được gọi là kiểu trả về hiệp biến .


8

Từ việc phát hành JDK 1.5, các kiểu hiệp biến đã được giới thiệu trong Java. và tôi sẽ giải thích cho bạn một trường hợp đơn giản: Khi chúng tôi ghi đè một hàm, hàm được phép thực hiện các thay đổi đối với hành vi của nó, đó là những gì bạn có thể đọc trong hầu hết các cuốn sách, nhưng những gì họ {tác giả} bỏ lỡ là chúng ta cũng có thể thay đổi kiểu trả về. kiểm tra liên kết dưới đây để làm rõ, chúng tôi có thể thay đổi kiểu trả về miễn là nó có thể được chỉ định để trả về kiểu Phiên bản cơ sở của phương thức.

Vì vậy, tính năng trả về các kiểu dẫn xuất này được gọi là COVARIANT ...

Các phương thức ghi đè có thể khác nhau về kiểu trả về không?


7

Các kiểu trả về đồng biến đơn giản có nghĩa là trả về tham chiếu Lớp riêng hoặc tham chiếu lớp con của nó.

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
Nó cũng bao gồm trường hợp Parent.foo()trả về kiểu không liên quanAChild.foo()trả về kiểu Bcó nguồn gốc từ A.
Davis Herring

2

Để thêm vào các câu trả lời ở trên, có thể ghi đè giữa các kiểu trả về đồng biến thể, với ràng buộc rằng kiểu trả về của phương thức ghi đè (phương thức lớp con) phải là lớp con của kiểu trả về của phương thức được ghi đè (phương thức lớp chồng). Điều này có hiệu lực từ Java 5 trở đi.


1

Kiểu trả về đồng biến chỉ định rằng kiểu trả về có thể thay đổi theo cùng hướng với lớp con

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

Trước Java 5, không thể ghi đè bất kỳ phương thức nào bằng cách thay đổi kiểu trả về. Nhưng bây giờ, kể từ Java5,

có thể ghi đè phương thức bằng cách thay đổi kiểu trả về nếu lớp con ghi đè bất kỳ phương thức nào có kiểu trả về là Không nguyên thủy nhưng nó thay đổi kiểu trả về thành kiểu lớp con.


1
  • Nó giúp tránh các phôi kiểu khó hiểu có trong hệ thống phân cấp lớp và do đó làm cho mã có thể đọc được, sử dụng được và có thể bảo trì được.
  • Chúng tôi có quyền tự do có các kiểu trả về cụ thể hơn khi ghi đè
    các phương thức.

  • Trợ giúp trong việc ngăn chặn ClassCastExceptions thời gian chạy trả lại

tham khảo: www.geeksforgeeks.org


0
  • Kiểu trả về hiệp phương sai trong java, cho phép thu hẹp kiểu trả về của phương thức bị ghi đè.
  • Tính năng này sẽ giúp tránh truyền xuống phía máy khách. Nó cho phép lập trình viên lập trình mà không cần kiểm tra kiểu và truyền xuống.
  • Kiểu trả về hiệp phương sai luôn chỉ hoạt động đối với kiểu trả về không nguyên thủy.
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();
    }
}

Ví dụ khác là từ 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

Trước Java5, không thể ghi đè bất kỳ phương thức nào bằng cách thay đổi kiểu trả về. Nhưng bây giờ, kể từ Java5, có thể ghi đè phương thức bằng cách thay đổi kiểu trả về nếu lớp con ghi đè bất kỳ phương thức nào có kiểu trả về là Không nguyên thủy nhưng nó thay đổi kiểu trả về thành kiểu lớp con.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.