[英]What is the differences between class ClassAny(credit: Any) and class UserAdmin<T>(credit:T) in Kotlin?
[英]What are the differences between Kotlin class properties and Java class fields
我已經開始學習 Kotlin。 我目前的背景是 Java。 我發現 Kotlin 中的類屬性與 Java 中的類字段有很大不同,盡管它們看起來很相似。 在他的問題中,我想匯總這兩者之間的所有技術差異。 這是我已經想通的:
Java 字段和隱藏 vs Kotli 屬性和覆蓋
(實際上這促使我寫這篇文章):
在Java中,基類的一個字段被派生類中的同名字段隱藏,所以使用哪個字段取決於對包含該字段的對象的引用類型,而不是對象本身的類型(字段不像方法那樣被覆蓋,因此它們不依賴於對象的運行時類型)。 例如這段代碼:
class A {
public String name = "A";
public void printMessage() {
System.out.println("Field accessed in method declared inside class A invoked form an object of " + getClass() + " : " + name);
}
}
class B extends A{
public String name = "B";
}
public class Main {
public static void main(String... args){
B b = new B();
System.out.println("Field from instance of class B pointed by reference to B : " + b.name);
A a = b;
System.out.println("Field from instance of class B pointed by reference to A : "+a.name);
a.printMessage();
}
}
打印這個:
Field from instance of class B pointed by reference to B : B
Field from instance of class B pointed by reference to A : A
Field accessed in method declared inside class A invoked form an object of class B : A
相比之下,Kotlin 屬性是由自動生成的 getter 和 setter 訪問的字段。 屬性被覆蓋(不隱藏),所以屬性訪問是在運行時解析的,與上面類似的代碼是用 Kotlin 編寫的:
open class A {
open val name = "A"
fun printMessage() {
println("Field accessed in method declared inside class A invoked form an object of $javaClass : $name")
}
}
class B(override val name : String = "B") : A()
fun main(args : Array<String>) {
val b : B = B()
println("Field from instance of class B pointed by reference to B : " + b.name)
val a : A = b;
println("Field from instance of class B pointed by reference to A : " + a.name)
a.printMessage()
}
打印這個:
Field from instance of class B pointed by reference to B : B
Field from instance of class B pointed by reference to A : B
Field accessed in method declared inside class A invoked form an object of class B : B
訪問權限
Java 字段默認是包私有的。 Kotlin 屬性默認是公開的。
默認初始化
Java 字段使用合理的默認值進行初始化(如此處所述: https : //docs.oracle.com/javase/tutorial/java/nutsandbolts/datatypes.html )。
每個 Kotlin 類屬性的創建方式都必須允許它在訪問時提供明確的給定值。 可以通過初始化器、構造器、設置器、延遲初始化來實現這一點:
class InitValues(val inCtor : String = "Given in constructor"){
var byInitializer = "In initializer"
var initializedWithNull : String? = null
val valueGivenByGetter
get() : String {
return "This value is given by getter"
}
val byLazyInit : String by lazy { "This is lazy init" }
}
但是必須給出應該返回的值——不會提供默認值。
在類字段/屬性方面是否還有其他技術差異可能會讓 Java 程序員在 Kotlin 中編寫代碼感到驚訝?
(我不是在談論附加功能,例如委托屬性,而是那些乍一看與 Java 中存在的相似並且可能具有誤導性的東西)
我想詳細說明 Java 字段和 Kotlin 屬性之間的區別。 查看以下 Java 字段和 Kotlin 屬性的示例。
Java 領域:
class Product {
public int discount = 20;
}
科特林屬性:
class Product {
var discount: Int = 20
}
上面的兩個例子是不等價的。 因為在 Kotlin 中,getter 和 setter 是為屬性自動生成的。 上面的 Kotlin 屬性等效於以下 Java 代碼:
class Product {
private int discount = 20;
public int getDiscount() {
return discount;
}
public void setDiscount(int port) {
this.discount = discount;
}
}
所以 Java 字段和 Kotlin 屬性的區別在於Kotlin 屬性創建了一個字段及其訪問器。 當屬性是val
,它只創建一個 getter。 當屬性是var
,它會創建一個 getter 和一個 setter。 並且該字段默認變為private
,如上面的代碼所示, discount
是private
。 但是您可以使用其 getter 和 setter 訪問discount
。
如果我們想在 Kotlin 的 getter 和 setter 中實現一些邏輯或驗證怎么辦? 例如,當有人為產品設置discount
時,我們希望確保它永遠不會超過 85%。 在這種情況下,我們可以為discount
屬性定義自定義訪問器,如下所示:
class Product {
var discount: Int = 20
set(value) {
if (value >= 85) {
field = 85
} else {
field = value
}
}
}
該field
是 Kotlin 中的保留關鍵字,它將值作為支持字段保存。 上面的代碼導致:
product.discount = 70;
println(product.discount) // 70
product.discount = 90;
println(product.discount) // 85
我們可以使用get()
方法對 getter 執行類似的操作。
就是這樣! 希望有幫助。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.