2017-07-12 28 views
5

Khi gọi mã Java từ Kotlin, có SAM conversion để mã Java như thế này:Sử dụng giao diện chức năng với các loại chức năng trong Kotlin

adapter.setOnClickListener(new OnClickListener() { 
    @Override 
    public void onClick(View view, int position) { 
     // Do stuff here 
    } 
}); 

có thể trông như thế này:

adapter.setOnClickListener { view, position -> 
    // Do stuff 
} 

Bây giờ, tôi đang làm việc trên dự án Kotlin và tôi muốn xác định giao diện chức năng làm người nghe sự kiện:

interface OnSomeActionListener { 

    fun onSomeAction(parameter1: Int, parameter2: String) 

} 

Trong SomeClass Tôi có một chức năng để thiết lập người nghe:

... 

    private var onSomeActionListener: OnSomeActionListener? = null 

    fun setOnSomeActionListener(listener: OnSomeActionListener) { 
     onSomeActionListener = listener 
    } 

    ... 

Và khi tôi tạo một thể hiện của lớp này và cố gắng gọi hàm setter, tôi làm điều đó như vậy:

val thing = SomeClass() 

thing.setOnSomeActionListener(object : OnSomeActionListener { 
    override fun onSomeAction(parameter1: Int, parameter2: String) { 
     // Do stuff here 
    } 
}) 

tôi nhận thức được rằng Kotlin có các loại chức năng do đó không hỗ trợ chuyển đổi SAM từ các trang web khác nhau như this one.

Tôi đã đọc một chút về các loại chức năng nhưng tôi chưa từng sử dụng chúng trước đây.

Tôi làm cách nào để viết lại mã của mình để tôi có thể gọi hàm setter như thế này?

val thing = SomeClass() 

thing.setOnSomeActionListener { parameter1, parameter2 -> 
    // Do stuff here 
} 

.

Trả lời

8

Một loại chức năng trông như thế này:

(Parameters) -> ReturnType 

Trong trường hợp của bạn, thay vì sử dụng loại giao diện, bạn có thể sử dụng (View, Int) -> Unit. Nó sẽ giống như thế này:

private var onSomeActionListener: ((View, Int) -> Unit)? = null 

fun setOnSomeActionListener(listener: (View, Int) -> Unit) { 
    onSomeActionListener = listener 
} 

private fun callSomeActionListener(view: View, position: Int) { 
    onSomeActionListener?.invoke(view, position) 
} 

Thêm tên

Trong các loại chức năng bạn cũng có thể chỉ định tên cho các thông số. Điều này không thay đổi nhiều theo mui xe nhưng họ có thể thêm một số rõ ràng ở đây và trong mã gọi điện thoại, đó là tốt đẹp.

(view: View, position: Int) -> Unit 

Sử dụng một loại bí danh

Để tránh phải gõ (View, Int) -> Unit mọi thời gian, bạn có thể định nghĩa một typealias:

typealias OnSomeActionListener = (view: View, position: Int) -> Unit 

Vì vậy, rằng mã của bạn bây giờ trông như thế này một lần nữa:

private var onSomeActionListener: OnSomeActionListener? = null 

fun setOnSomeActionListener(listener: OnSomeActionListener?) { 
    onSomeActionListener = listener 
} 

Và để gọi nó là:

val thing = SomeClass() 

thing.setOnSomeActionListener { view, position -> 
    // Do stuff here 
} 
+0

Cảm ơn cho câu trả lời. Tôi nghĩ nội dung được chia thành các phần rõ ràng và được viết như một hướng dẫn từng bước rất hữu ích. –

0

Vâng, một cái gì đó như thế này:

// declare a variable of nullable function type: 
var onSomeActionListener: ((Int, String) -> Unit)? = null 

// declare higher-order function: 
fun setOnSomeActionListener(listener: (Int, String) -> Unit) { 
    onSomeActionListener = listener 
} 

// set listener: 
val listener: (Int, String) -> Unit = { p1, p2 -> { /* some stuff */ } } 
setOnSomeActionListener(listener) 

// or in one line: 
setOnSomeActionListener { p1, p2 -> { /* some stuff */ } } 

Để biết thêm thông: Higher-Order Functions and Lambdas

0

Làm thế nào về việc xác định chức năng chấp nhận một hàm và trả về một giao diện?

fun makeOnSomeActionListener(f: (Int,String) -> Unit) = object : OnSomeActionListener { 
    override fun onSomeAction(parameter1: Int, parameter2: String) = f(parameter1, parameter2) 
} 

Giao diện đại biểu công việc của nó là f.

Sau đó, bạn có thể viết

val thing = SomeClass() 

thing.setOnSomeActionListener(makeOnSomeActionLisener { parameter1, parameter2 -> 
    // Do stuff here 
}) 
Các vấn đề liên quan