Tôi không thể hiểu và tôi không thể tìm thấy ý nghĩa của từ khóa out trong kotlin.
Bạn có thể kiểm tra ví dụ ở đây:
List<out T>
Nếu ai có thể giải thích ý nghĩa của điều này. Nó sẽ thực sự được đánh giá cao.
Tôi không thể hiểu và tôi không thể tìm thấy ý nghĩa của từ khóa out trong kotlin.
Bạn có thể kiểm tra ví dụ ở đây:
List<out T>
Nếu ai có thể giải thích ý nghĩa của điều này. Nó sẽ thực sự được đánh giá cao.
Câu trả lời:
Với chữ ký này:
List<out T>
bạn có thể làm được việc này:
val doubleList: List<Double> = listOf(1.0, 2.0)
val numberList: List<Number> = doubleList
có nghĩa là T là hiệp phương sai :
khi một loại tham số T của một lớp C được khai báo ra , C <cơ sở> một cách an toàn có thể là một siêu kiểu của C <nguồn gốc> .
Điều này trái ngược với in , ví dụ
Comparable<in T>
bạn có thể làm được việc này:
fun foo(numberComparable: Comparable<Number>) {
val doubleComparable: Comparable<Double> = numberComparable
// ...
}
mà có nghĩa là T là contravariant :
khi một loại tham số T của một lớp C được khai báo trong , C <nguồn gốc> một cách an toàn có thể là một siêu kiểu của C <cơ sở> .
Một cách khác để ghi nhớ nó:
Người tiêu dùng trong , Nhà sản xuất ra .
----------------- cập nhật vào ngày 4 tháng 1 năm 2019 -----------------
Đối với " Consumer in, Producer out ", chúng ta chỉ đọc từ Producer - phương thức gọi để nhận kết quả loại T; và chỉ ghi vào phương thức gọi của Người tiêu dùng bằng cách truyền vào tham số kiểu T.
Trong ví dụ List<out T>
, rõ ràng là chúng ta có thể làm điều này:
val n1: Number = numberList[0]
val n2: Number = doubleList[0]
Vì vậy, nó là an toàn để cung cấp List<Double>
khi List<Number>
được mong đợi, do đó List<Number>
là siêu loại List<Double>
, nhưng không phải ngược lại.
Trong ví dụ cho Comparable<in T>
:
val double: Double = 1.0
doubleComparable.compareTo(double)
numberComparable.compareTo(double)
Vì vậy, nó là an toàn để cung cấp Comparable<Number>
khi Comparable<Double>
được mong đợi, do đó Comparable<Double>
là siêu loại Comparable<Number>
, nhưng không phải ngược lại.
out
một phần không phải là thứ tạo nên sự List
bất biến. Bạn có thể dễ dàng tạo List<out T>
giao diện của riêng mình có clear()
phương thức vì nó không yêu cầu bất kỳ đối số nào.
List<out T> is like List<? extends T> in Java
và
List<in T> is like List<? super T> in Java
Ví dụ trong Kotlin, bạn có thể làm những việc như
val value : List<Any> = listOf(1,2,3)
//since List signature is List<out T> in Kotlin
List<out T>
có nghĩa là bạn có thể làm val list: List<Number> = listOf<Int>()
vì Int
là một loại dẫn xuất của Number
. Java tương đương sẽ làList<? extends Number> list = new ArrayList<Integer>();
Tham khảo hướng dẫn sử dụng kotlin
Kiểu Kotlin
List<out T>
là một giao diện cung cấp các thao tác chỉ đọc như kích thước, lấy, v.v. Giống như trong Java, nó kế thừa từCollection<T>
và đến lượt nó kế thừa từIterable<T>
. Các phương thức thay đổi danh sách được thêm vào bởiMutableList<T>
giao diện. Mô hình này cũng giữ choSet<out T>/MutableSet<T>
vàMap<K, out
V>/MutableMap<K, V>
Và điều này,
Trong Kotlin, có một cách để giải thích loại thứ này cho trình biên dịch. Đây được gọi là phương sai của trang web khai báo: chúng ta có thể chú thích tham số kiểu T của Nguồn để đảm bảo rằng tham số này chỉ được trả lại (được sản xuất) từ các thành viên của
Source<T>
và không bao giờ được tiêu thụ. Để làm điều này, chúng tôi cung cấp công cụ sửa đổi:
> abstract class Source<out T> { > abstract fun nextT(): T } > > fun demo(strs: Source<String>) { > val objects: Source<Any> = strs // This is OK, since T is an out-parameter > // ... }
Nguyên tắc chung là: khi một tham số kiểu
T
của một lớpC
được khai báo, nó có thể chỉ xảy ra ở vị trí ngoài trong các thành viên củaC
, nhưng đổi lạiC<Base>
có thể an toàn là một kiểu siêu củaC<Derived>
.Trong "các từ thông minh", họ nói rằng lớp
C
là hiệp phương sai trong tham sốT
, hoặc đóT
là một tham số kiểu hiệp phương sai. Bạn có thể coi C là nhà sản xuất của T, chứ KHÔNG phải là người tiêu dùng củaT
's. Công cụ sửa đổi out được gọi là chú thích phương sai và vì nó được cung cấp tại trang khai báo tham số kiểu, chúng ta nói về phương sai của trang khai báo. Điều này trái ngược với phương sai trang web sử dụng của Java trong đó các ký tự đại diện trong cách sử dụng kiểu làm cho các kiểu đồng biến.
Hãy nhớ như thế này:
in
là "cho vào " - bạn muốn đặt (viết) một cái gì đó vào đó (vì vậy đó là "người tiêu dùng")
out
là "for out put" - bạn muốn lấy (đọc) thứ gì đó từ nó (vì vậy nó là "nhà sản xuất")
Nếu bạn đến từ Java,
<in T>
là đầu vào, vì vậy nó giống như <? super T>
(người tiêu dùng)
<out T>
là cho đầu ra, vì vậy nó giống như <? extends T>
(nhà sản xuất)
List<out T>
khai báo làout
làm cho nó không thể thay đổi (so với các bộ sưu tập có thể thay đổi, không có). Có thể hữu ích khi đề cập và nhấn mạnh điều đó trong câu trả lời. Truyền ngầm là hệ quả của điều này chứ không phải là điểm chính (vì người ta không thể ghi vào Danh sách <Số>, an toàn khi có nó như một tham chiếu đến Danh sách <Đôi>).