2016-11-21 16 views
5

xem xét lớp học này với hai chức năng, một với Int luận, khác với chung một:Làm thế nào để đối phó với một độ phân giải quá tải độ phân giải của các chức năng với generics?

class C<K, V> { 
    // ... 

    operator fun f(index: Int): Pair<K, V> = ... 
    operator fun f(key: K): V = ... 
} 

Khi nó là tham số như C<Int, SomeType>, KInt, và cả hai chức năng phù hợp với các cuộc gọi, kết quả vào một lỗi :

val m = C<Int, SomeType>() 
m.f(1) 

Overload resolution ambiguity. All these functions match:

  • public final fun f(index: Int): SomeType defined in C
  • public final fun f(key: Int): Pair<Int, SomeType>? defined in C

làm thế nào để gọi bất cứ f tôi muốn trong trường hợp này?

Trả lời

7

Nếu bạn đủ may mắn để có những cái tên tham số khác nhau của các chức năng, sử dụng named arguments sẽ làm các trick:

m.f(index = 1) // calls f(index: Int) 
m.f(key = 1) // calls f(key: K) 

Ngược lại, nếu những cái tên thông số đều giống nhau (hoặc định nghĩa trong Java), một có thể workaround là để thực hiện unchecked casts để làm cho trình biên dịch chọn tùy chọn mong muốn:

  • để gọi f(index: Int), bạn có thể sử dụng

    @Suppress("UNCHECKED_CAST") 
    val s = (m as C<*, SomeType>).f(1) as Pair<Int, SomeType> 
    

    Dàn diễn viên để C<*, SomeType>makes K equivalent to in Nothing, out Any, có nghĩa là không có đối số hợp lệ cho f(key: K), vì vậy cuộc gọi được một cách tự nhiên để giải quyết f(index: Int), nhưng bạn cần phải đúc kết quả trở lại, bởi vì nếu không nó là Pair<Any, SomeType>.

  • Để gọi f(key: K), sử dụng:

    @Suppress("UNCHECKED_CAST") 
    val s = (m as C<Any, SomeType>).f(1 as Any) 
    

    Tương tự như vậy, các diễn viên để C<Any, SomeType> thay đổi chữ ký của chức năng mong muốn để f(key: Any), và gọi nó, chỉ cần bị ném lên trời 1-Any.

Đó là tất cả như nhau trong trường hợp một vài thông số kiểu xung đột (ví dụ f(key: K)f(value: V) khi KV đều SomeType), chỉ cần sử dụng đối số tên hoặc đúc các đối tượng để cấm một trong những chức năng (in Nothing) hoặc để làm cho nó chấp nhận Any.

0

Kotlin stdlib sử dụng quy ước fun fAt(index: Int) để giải quyết các trường hợp như vậy.

+1

Đó là sự thật, nhưng điều đó đòi hỏi một số suy nghĩ trước để thiết kế lớp 'C' ngăn chặn xung đột chữ ký có thể với Generics thay thế. Và nếu bạn phải đối mặt với lớp học như vậy và không có cách nào để đổi tên các chức năng của nó, bạn phải sử dụng các thủ thuật chung từ câu trả lời của @ hotkey. – Ilya

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