2017-08-18 19 views
11

Tôi đã đọc this question nhưng tôi có câu hỏi cơ bản hơn về từ khóa crossinline. Tôi không thực sự chắc chắn nó đang giải quyết vấn đề gì và nó giải quyết nó như thế nào.Từ khóa chéo của Kotlin

Từ the Kotlin Docs,

Lưu ý rằng một số chức năng inline có thể gọi lambdas truyền cho họ như là các thông số không trực tiếp từ các cơ quan chức năng, nhưng từ một bối cảnh thực hiện, chẳng hạn như một đối tượng cục bộ hoặc một hàm lồng nhau. Trong trường hợp như vậy, luồng kiểm soát không phải cục bộ cũng không được phép trong lambdas. Để chỉ ra rằng, tham số lambda cần phải được đánh dấu bằng modifier crossinline:

[Nhấn mạnh thêm]

Tuyên bố này là mơ hồ đối với tôi. Đầu tiên, tôi gặp khó khăn khi thực sự hình dung những gì có nghĩa là "trường hợp như vậy". Tôi có một ý tưởng chung về vấn đề là gì nhưng không thể đưa ra một ví dụ hay về nó.

Thứ hai, cụm từ "Để chỉ ra rằng" có thể được đọc theo nhiều cách. Để chỉ ra cái gì? Không được phép trường hợp cụ thể? Rằng nó được phép? Dòng điều khiển phi cục bộ đó trong định nghĩa hàm đã cho là (hoặc không được) cho phép?

Tóm lại, tôi gặp khó khăn trong việc tìm hiểu ngữ cảnh sử dụng điều này thực sự là gì, ngữ cảnh sử dụng nó giao tiếp với khách hàng, và kết quả mong đợi của việc áp dụng từ khóa này là gì.

Trả lời

10

Trước tiên, tôi gặp sự cố khi thực sự mô tả ý nghĩa của "trường hợp như vậy". Tôi có một ý tưởng chung về vấn đề là gì nhưng không thể đưa ra một ví dụ hay về nó.

Dưới đây là một ví dụ:

interface SomeInterface { 
    fun someFunction(): Unit 
} 

inline fun someInterfaceBy(f:() -> Unit): SomeInterface { 
    return object : SomeInterface { 
     override fun someFunction() = f() 
     //       ^^^ 
     // Error: Can't inline 'f' here: it may contain non-local returns. 
     // Add 'crossinline' modifier to parameter declaration 'f'. 
    } 
} 

Ở đây, chức năng đó sẽ được chuyển cho someInterfaceBy { ... } được inlined bên trong một lớp vô danh thực hiện SomeInterface. Việc biên soạn từng trang web gọi someInterfaceBy sẽ tạo ra một lớp mới với cách triển khai khác nhau là someFunction().

Để xem những gì có thể đi sai, hãy xem xét một cuộc gọi của someInterfaceBy { ... }:

fun foo() { 
    val i = someInterfaceBy { return } 
    // do something with `i` 
} 

Bên trong lambda inline, return is non-local và thực sự có nghĩa trở về từ foo. Nhưng vì lambda không được gọi và rò rỉ vào đối tượng i, trở về từ foo có thể hoàn toàn vô nghĩa: nếu i.someFunction() (và do đó lambda) được gọi sau foo đã trả về hoặc thậm chí trong một chủ đề khác?

quát, 'trường hợp này' nghĩa inline chức năng gọi thông số chức năng của họ không phải trong cơ thể của mình (một cách hiệu quả, tức là dùng chức năng inline khác vào tài khoản) nhưng bên trong một số chức năng khác mà họ tuyên bố, giống như trong lambdas phi inline và các đối tượng ẩn danh.


Thứ hai, cụm từ "Để chỉ ra rằng," có thể được đọc nhiều cách khác nhau. Để chỉ ra cái gì? Đó là một trường hợp cụ thể không được phép? Điều đó được cho phép? Dòng điều khiển phi cục bộ đó trong định nghĩa hàm đã cho là (hoặc không được) cho phép?

Đây chính là cách vấn đề tôi đã mô tả ở trên là cố định trong thiết kế ngôn ngữ Kotlin: bất cứ khi nào một chức năng inline dự định nội tuyến tham số chức năng của nó ở đâu đó, nơi nó có thể được không được gọi tại chỗ nhưng lưu trữ và sau đó gọi , tham số của hàm inline phải được đánh dấu là crossinline, cho biết luồng điều khiển không cục bộ không được phép trong lambda được thông qua tại đây.

+0

Vì vậy, từ khóa 'crossinline' ngăn chặn lambda chứa từ khóa' return' (kết quả là trả về không phải cục bộ) sẽ không có ý nghĩa xác định từ cách lambda được sử dụng trong hàm. – melston

+0

Tôi cũng giả định rằng việc trả lại nhãn không bị ảnh hưởng bởi việc sử dụng 'crossinline', đúng không? – melston

+0

@melston, vâng, miễn là * local *. Nghĩa là, 'someList.forEach {item -> someCrossInline {return @ forEach item}}' không được phép, bởi vì đó là sự trả về không phải cục bộ cho lambda 'crossinline', nhưng' someList.forEach {item -> someCrossInline {return @someCrossInline item}} 'là tốt (xin lỗi cho mã lớn trong một bình luận). – hotkey

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