2017-03-21 14 views
15

Trong Kotlin, đoạn mã sau biên dịch:Làm thế nào để xóa công việc trong Kotlin?

class Foo { 
    fun bar(foo: List<String>): String { 
     return "" 
    } 

    fun bar(foo: List<Int>): Int { 
     return 2; 
    } 
} 

Mã này, tuy nhiên, không:

class Foo { 
    fun bar(foo: List<String>): String { 
     return "" 
    } 

    fun bar(foo: List<Int>): String { 
     return "2"; 
    } 
} 

Biên soạn này sẽ gây ra các lỗi sau:

Error:(8, 5) Kotlin: Platform declaration clash: The following declarations have the same JVM signature (foo(Ljava/util/List;)Ljava/lang/String;): 
    fun foo(layout: List<Int>): String 
    fun foo(layout: List<String>): String 

Trong Java, không phải ví dụ nào sẽ biên dịch:

class Foo { 
    String bar(List<Integer> foo) { 
     return ""; 
    } 

    Integer bar(List<String> foo) { 
     return 2; 
    } 
} 

class Foo { 
    String bar(List<Integer> foo) { 
     return ""; 
    } 

    String bar(List<String> foo) { 
     return "2"; 
    } 
} 

ngạc nhiên, cả hai đoạn trước khi tạo ra lỗi biên dịch quen thuộc:

Error:(13, 12) java: name clash: bar(java.util.List<java.lang.String>) and bar(java.util.List<java.lang.Integer>) have the same erasure 

gì làm tôi ngạc nhiên là các ví dụ Kotlin đầu tiên làm việc ở tất cả, và thứ hai, nếu nó hoạt động, tại sao Kotlin ví dụ thứ hai thất bại ? Kotlin có xem xét kiểu trả về của phương thức như một phần của chữ ký của nó không? Hơn nữa, tại sao chữ ký phương thức trong Kotlin lại tôn trọng kiểu tham số đầy đủ, ngược lại với Java?

Trả lời

13

Thực ra Kotlin biết sự khác biệt giữa hai phương pháp trong ví dụ của bạn, nhưng jvm sẽ không. Đó là lý do tại sao đó là một cuộc đụng độ "nền tảng".

Bạn có thể làm ví dụ thứ hai của bạn biên dịch bằng công @JvmName chú thích:

class Foo { 
    @JvmName("barString") fun bar(foo: List<String>): String { 
    return "" 
    } 

    @JvmName("barInt") fun bar(foo: List<Int>): String { 
    return "2"; 
    } 
} 

chú thích này tồn tại vì lý do này rất. Bạn có thể đọc thêm trong số interop documentation.

+0

Nhưng tại sao ví dụ Kotlin đầu tiên biên dịch mà không có chú thích này? Liệu JVM có nhận ra các phương thức với các kiểu trả về khác nhau không? Theo [câu trả lời này] (http://stackoverflow.com/a/16149445/1772342), kiểu trả về không phải là một phần của chữ ký của phương thức. – breandan

+0

Ah, tôi hiểu rồi. Có lẽ Java không cho phép các phương thức tên/tham số giống nhau với các kiểu trả về khác nhau trong khi biên dịch, nhưng JVM nhận ra chúng? – breandan

+4

@breandan cũng có, kiểu trả về là một phần của chữ ký, nhưng trong trường hợp đầu tiên nó khác nhau cho hai phương thức, (mặc dù kiểu xóa tham số là giống nhau) vì vậy chữ ký khác nhau. Chúng là 'foo (Ljava/util/List;) Ljava/lang/String;' và 'foo (Ljava/util/List;) Ljava/lang/Integer;' tương ứng. Java chỉ xem xét các kiểu tham số và tên phương thức trong kiểm tra xung đột tên để ví dụ đầu tiên trong Java không được biên dịch. Điều này là nhiều hơn về quá tải và anot loại tẩy xoá và có thể dễ dàng cố định trong ngôn ngữ (như Kotlin đã làm) – Strelok

Các vấn đề liên quan