2015-01-29 35 views
63

Làm thế nào để bạn xác định một phương pháp mở rộng tĩnh trong Kotlin? Điều này thậm chí có thể? Tôi hiện đang có một phương pháp mở rộng như hình dưới đây.Phương pháp mở rộng tĩnh trong Kotlin

public fun Uber.doMagic(context: Context) { 
    // ... 
} 

Tiện ích mở rộng trên có thể được gọi trên một phiên bản.

uberInstance.doMagic(context) // Instance method 

nhưng làm cách nào để làm cho phương pháp tĩnh như được hiển thị bên dưới.

Uber.doMagic(context)   // Static or class method 
+1

Ý của bạn là gì theo "phương pháp mở rộng tĩnh"? –

+2

Một phương pháp mà tôi có thể gọi mà không cần một cá thể, nhưng vẫn là một phần mở rộng của lớp. (Các phương thức tĩnh Java thông thường) –

+0

Tôi nghĩ rằng nó có thể không phải là mục đích sử dụng của [phần mở rộng Kotlin] (http://kotlinlang.org/docs/reference/extensions.html) câu hỏi hay, tôi đã nghĩ về cùng một điều trong khi cố gắng suy luận khái niệm C#. Nhưng trong khi thực tế việc sử dụng khá giống nhau. Kotlin mở rộng, trong khi họ yêu cầu được gửi đi tĩnh, họ cảm thấy như tự động "đính kèm", nếu có một điều như vậy, hoặc cuối bị ràng buộc để dụ. Nếu tôi không nhầm lẫn ... hoặc có lẽ tôi đã nhận nó hoàn toàn sai :) – Dan

Trả lời

61

Để đạt Uber.doMagic(context), bạn có thể viết một phần mở rộng đến số companion object của Uber (yêu cầu khai báo đối tượng đồng hành):

class Uber { 
    companion object {} 
} 

fun Uber.Companion.doMagic(context: Context) { } 
+20

Điều này là tốt đẹp nhưng nếu đó là một lớp Java hoặc một lớp học mà không có bạn đồng hành thì sao? – Jire

+18

@Jire cho các trường hợp như vậy, không có hỗ trợ trong Kotlin 1.0 –

+1

Tôi có thể thấy một usecase trong việc mở rộng các lớp khung JVM với các giá trị mặc định, ví dụ: String.DEFAULT hoặc Int.DEFAULT, trong trường hợp logic miền của bạn yêu cầu điều này (hiện tại của tôi, kết hợp với các lớp dữ liệu trống). –

5

Bạn có thể tạo một phương pháp tĩnh với việc sử dụng đối tượng Companion như:

class Foo { 
    // ... 
    companion object { 
     public fun bar() { 
      // do anything 
     } 
    } 
} 

và sau đó bạn có thể gọi nó thích:

class Baz { 
    // ... 
    private fun callBar() { 
     Foo.bar() 
    } 
} 
+0

Tôi tin rằng đó không phải là thực sự tĩnh. Các đối tượng đồng hành cho phép bạn gọi bằng tên lớp, nhưng vẫn sử dụng một thể hiện của lớp. Ngoài ra, câu hỏi là về các hàm mở rộng tĩnh, không chỉ các hàm tĩnh. Tuy nhiên, để có các hàm tĩnh, bạn có thể sử dụng chú thích 'platformStatic'. –

+1

'platformStatic' được đổi tên thành' JvmStatic' trong Kotlin hiện tại. –

-1

Tôi cũng khá thích có khả năng thêm các phương pháp mở rộng tĩnh trong Kotlin. Như một giải pháp cho bây giờ tôi đang thêm phương thức exntension vào nhiều lớp thay vì sử dụng một phương thức mở rộng tĩnh trong tất cả chúng.

class Util  

fun Util.isDeviceOnline(context: Context): Boolean { 
    val connMgr = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager 
    val networkInfo = connMgr.activeNetworkInfo 
    return networkInfo != null && networkInfo.isConnected 
} 

fun Activity.isDeviceOnline(context: Context) = { Util().isDeviceOnline(context) } 
fun OkHttpClient.isDeviceOnline(context: Context) = { Util().isDeviceOnline(context) } 
+0

Câu hỏi ban đầu là về cách một javaclass có thể được mở rộng với một * phương pháp tĩnh *. Trong trường hợp của bạn, điều đó có nghĩa là có thể gọi theo nghĩa đen là 'Activity.isDeviceOnline (...)' mà không có một thể hiện của 'Activity'. –

8

Đây là những gì các tài liệu chính thức cho biết:

Kotlin tạo ra phương pháp tĩnh cho các chức năng gói cấp. Kotlin cũng có thể tạo các phương thức tĩnh cho các hàm được định nghĩa trong các đối tượng có tên là hoặc các đối tượng đồng hành nếu bạn chú thích các hàm đó là @JvmStatic. Ví dụ:

Kotlin static methods

class C { 
    companion object { 
    @JvmStatic fun foo() {} 
    fun bar() {} 
    } 
} 

Bây giờ, foo() là tĩnh trong Java, trong khi quầy bar() không phải là:

C.foo(); // works fine 
C.bar(); // error: not a static method 
0

đề nghị bạn nhìn vào Liên kết this. Như bạn thấy đó, bạn chỉ cần khai báo phương pháp ở cấp cao nhất của gói (file):

package strings 
public fun joinToString(...): String { ... } 

Đây là bằng

package strings; 

public class JoinKt { 
    public static String joinToString(...) { ... } 
} 

Với CONSTANS tất cả mọi thứ đều giống nhau. Đây khai

val UNIX_LINE_SEPARATOR = "\n" 

bằng

public static final String UNIX_LINE_SEPARATOR = "\n"; 
1

Nếu bạn làm theo phong cách của văn bản tĩnh học ở phía trên cùng của lớp trong Java, sau đó tôi đề nghị để cố gắng xem xét viết họ ở cấp cao nhất (ví dụ như trước khi khai báo lớp) trong Kotlin.Đối với nhiều trường hợp sử dụng, nó hoạt động tốt hơn so với giới thiệu một người bạn đồng phản đối

Sample Code:

class Person { 
companion object Test { 
    fun callMe() = println("I'm called.") 
} 

} 

fun main(args: Array<String>) { Person.callMe()} 

Khi bạn chạy chương trình, đầu ra sẽ là:

Tôi đang gọi.

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