2016-12-17 30 views
10

Tôi muốn tận dụng lợi thế của kotlin khi biểu thức và các phương thức chung để đơn giản hóa các ưu tiên chia sẻ api của Android.Kotlin - khi biểu thức có kiểu trả về của hàm

Thay vì gọi getString() & getInt() vv mọi lúc, điều tôi muốn làm là tạo một hàm mở rộng sẽ chuyển đổi dựa trên kiểu trả về của hàm và gọi phương thức thích hợp. Một cái gì đó như sau:

fun <T> SharedPreferences.get(key: String): T? { 
     when (T) { //how do I switch on return type and call appropriate function? 
      is String -> getString(key, null) 
      is Int -> getInt(key, -1) 
      is Boolean -> getBoolean(key, false) 
      is Float -> getFloat(key, -1f) 
      is Long -> getLong(key, -1) 
     } 
     return null 
    } 

Tất nhiên, nó sẽ không hoạt động. Nhưng có giải pháp nào để sử dụng khi biểu thức cho kiểu trả về của hàm không? Tất cả các đề xuất đều được chào đón.

Trả lời

9

Để đạt được chính xác những gì bạn muốn, bạn có thể sử dụng reified type parameters. Điều này sẽ làm cho trình biên dịch nội tuyến chức năng của bạn tại các trang web cuộc gọi của nó với T được thay thế bằng loại được sử dụng tại trang web cuộc gọi.

Chức năng sẽ trông như thế:

@Suppress("IMPLICIT_CAST_TO_ANY") 
inline operator fun <reified T> SharedPreferences.get(key: String): T? = 
    when (T::class) { 
     String::class -> getString(key, null) 
     Int::class -> getInt(key, -1) 
     Boolean::class -> getBoolean(key, false) 
     Float::class -> getFloat(key, -1f) 
     Long::class -> getLong(key, -1) 
     else -> null 
    } as T? 

Nếu bạn thực hiện get một operator function, bạn cũng có thể gọi nó là sử dụng cú pháp điều hành: prefs[name].

Các cuộc gọi nên, tất nhiên, cung cấp đầy đủ thông tin kiểu cho trình biên dịch để suy ra T:

val i: Int? = prefs["i"] // OK, the type information is taken from the declaration 
val j: Int = prefs["i"]!! // OK 

val x = prefs["x"] // Error, not enough type information 
val y = prefs.get<String>("y") // OK, the type will be `String?` 

fun f(z: Int) = z 
f(prefs["z"]!!) // OK, the type information is taken from the parameter type 
+0

thú vị ... cảm ơn. Nhưng "Điều này sẽ làm cho trình biên dịch nội tuyến chức năng của bạn". Bạn có thể giải thích cho tôi những gì inlining actaully làm. Tôi đọc các tài liệu nhưng nó cho thấy rằng nội tuyến liên kết với một cái gì đó khác nhau như [hiệu suất] (http://stackoverflow.com/a/145841/3830694). Tôi không phải là một chuyên gia. Bạn có thể giải thích trong thuật ngữ đơn giản những gì nội tuyến thực sự làm gì? –

+1

@KrupalShah, trong Kotlin, ['inline' functions] (https://kotlinlang.org/docs/reference/inline-functions.html) thực sự không có ý định trở thành một công cụ hiệu suất bởi vì JVM tự quản lý các hàm nội tuyến trong thời gian chạy tốt đủ. Thay vào đó, các hàm 'inline' được sử dụng để linh hoạt. Hai trường hợp sử dụng chính là [tham số kiểu được sửa đổi] (https://kotlinlang.org/docs/reference/inline-functions.html#reified-type-parameters) và [luồng kiểm soát không cục bộ] (https: // kotlinlang .org/docs/reference/inline-functions.html # non-local-returns) ('break' và' continue' có thể được thêm vào 'return' trong tương lai). – hotkey

+1

@KrupalShah, lưu ý rằng cả hai trường hợp sử dụng đều yêu cầu cơ thể chức năng được chuyển đổi (đối với các generics được thay đổi, tham số kiểu được thay thế bằng kiểu hiện diện tại trang gọi, vì nếu không tham số kiểu sẽ bị xóa [https: // docs .oracle.com/javase/tutorial/java/generics/erasure.html) và mã không thể sử dụng nó; đối với luồng điều khiển, đối số chức năng được gạch chân, để 'trả về' bên trong nó sẽ hoạt động với hàm ngoài) . Các phép biến đổi này được thực hiện cho từng cuộc gọi hàm và mã được chuyển đổi sau đó được gạch chân tại các trang gọi. – hotkey

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