kotlin数据类
In this tutorial, we’ll look at Kotlin Data Class. If you haven’t read the Kotlin Classes post, we recommend you to do so before proceeding.
在本教程中,我们将研究Kotlin数据类。 如果您还没有阅读Kotlin Classes帖子,我们建议您在继续之前阅读。
您是否厌倦了用Java为POJO数据类编写数千行代码?
Every Java Programmer at some stage must have taken a note of the number of lines of code they need to write for classes that just need to store some data. Let’s see how a Book.java
POJO class looks like:
每个Java程序员在某个阶段都必须记下他们需要为只需要存储一些数据的类编写的代码行数。 让我们看看Book.java
POJO类的样子:
public class Book {
private String name;
private String authorName;
private long lastModifiedTimeStamp;
private float rating;
private int downloads;
public Book(String name, String authorName, long lastModified, float rating, int downloads) {
this.name = name;
this.authorName = authorName;
this.lastModifiedTimeStamp = lastModified;
this.rating = rating;
this.downloads = downloads;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAuthorName() {
return authorName;
}
public void setAuthorName(String authorName) {
this.authorName = authorName;
}
public long getLastModifiedTimeStamp() {
return lastModifiedTimeStamp;
}
public void setLastModifiedTimeStamp(long lastModifiedTimeStamp) {
this.lastModifiedTimeStamp = lastModifiedTimeStamp;
}
public float getRating() {
return rating;
}
public void setRating(float rating) {
this.rating = rating;
}
public int getDownloads() {
return downloads;
}
public void setDownloads(int downloads) {
this.downloads = downloads;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Book that = (Book) o;
if (downloads != that.downloads)
return false;
if (name != null ? !name.equals(that.name) :
that.name != null) {
return false;
}
return authorName != null ?
authorName.equals(that.authorName) :
that.authorName == null;
}
@Override
public int hashCode() {
int result = name != null ? name.hashCode() : 0;
result = 31 * result + (authorName != null ?
authorName.hashCode() : 0);
result = 31 * result + downloads;
return result;
}
@Override
public String toString() {
return "Book{" +
"name='" + name + '\'' +
", author='" + authorName + '\'' +
", lastModifiedTimestamp='" + lastModifiedTimeStamp + '\'' +
", rating='" + rating + '\'' +
", downloads=" + downloads +
'}';
}
}
WOAH! That’s 96 lines of code for just storing 5 fields in an object. We aren’t doing much here besides having getter setters, toString()
, equals()
and hashCode()
methods.
哇! 这是96行代码,仅在一个对象中存储5个字段。 除了拥有getter设置器, toString()
, equals()
和hashCode()
方法之外,我们在这里没有做太多事情。
With the clean architectures and separation of code practices in our practices, we need to create POJO classes since every project needs to store data somewhere. This can increase the boilerplate code.
在我们的实践中采用干净的体系结构和代码实践的分离之后,我们需要创建POJO类,因为每个项目都需要将数据存储在某个地方。 这可以增加样板代码。
This is where Kotlin comes to the rescue, with the use of Data Classes.
这就是Kotlin使用数据类进行救援的地方。
Data Classes is Kotlin’s answer to reducing boilerplate code.
数据类是Kotlin对减少样板代码的答案。
The above POJO class can be written in Kotlin in the following way:
上面的POJO类可以通过以下方式用Kotlin编写:
data class Book(var name: String, var authorName: String, var lastModified: Long, var rating: Float, var downloads: Int)
THAT’S IT. Kotlin converts a 96 line java code to a single line of code.
而已。 Kotlin将96行的Java代码转换为单行代码。
This is Kotlin’s way of reducing the boilerplate code in your project!
这是Kotlin减少项目中样板代码的方式!
Following are the requirements for creating Kotlin Data class.
以下是创建Kotlin Data类的要求。
data
您需要在类中添加关键字data
val
or a var
assigned.val
or a var
isn’t compulsory. 主构造函数的每个参数都必须分配一个val
或var
。 val
或var
。 abstract
, open
, sealed
or inner
数据类不能附加abstract
, open
, sealed
或inner
Kotlin Data class automatically creates the following functions for you.
Kotlin Data类自动为您创建以下功能。
equals()
and hashCode()
equals()
和hashCode()
toString()
of the form "Book(name=JournalDev, authorName=Anupam)"
toString()
的形式为"Book(name=JournalDev, authorName=Anupam)"
componentN()
functions for each of the parameters in the order specified. This is known as destructuring declarations. componentN()
按指定的顺序对每个参数起作用。 这称为解构声明。 copy()
copy()
Following are some features that a Data Class provides.
以下是数据类提供的一些功能。
open
). 数据类允许子类化(无需提及关键字open
)。 equals()
hashCode()
and toString()
您可以为equals()
hashCode()
和toString()
函数提供显式实现 copy()
and componentN()
functions are not allowed. 不允许对copy()
和componentN()
函数进行显式实现。 data class Book(var name: String,private var authorName: String, var lastModified: Long, var rating: Float, var downloads: Int)
我们可以通过在构造函数中指定可见性修饰符来控制getter和setter的可见性,如下所示。 Following is our data class:
以下是我们的数据类:
data class Book(var name: String, var authorName: String, var lastModified: Long, var rating: Float, var downloads: Int)
None of the parameters have a default value set. So we need to set an argument for each of them in the instantiation as shown below.
这些参数均未设置默认值。 因此,我们需要在实例化中为每个参数设置一个参数,如下所示。
fun main(args: Array) {
val book = Book("Android Tutorials","Anupam", 1234567, 4.5f, 1000)
}
Let’s set a few default arguments and see how the instantiation changes.
让我们设置一些默认参数,看看实例化如何变化。
data class Book(var name: String, var authorName: String = "Anupam", var lastModified: Long = 1234567, var rating: Float = 5f, var downloads: Int = 1000)
fun main(args: Array) {
var book = Book("Android tutorials","Anupam", 1234567, 4.5f, 1000)
book = Book("Kotlin")
book = Book("Swift",downloads = 500)
book = Book("Java","Pankaj",rating = 5f, downloads = 1000)
book = Book("Python","Shubham",rating = 5f)
}
Instead of setting each argument, we can set only the non-default ones and the ones which we wish too using the named argument.
Using Named Arguments, we can set the 5th argument as the second one by explicitly specifying the parameter name followed by =
. Life is so easier this way!
除了设置每个参数,我们还可以使用named参数仅设置非默认参数和我们希望设置的参数 。
通过使用命名参数,我们可以通过显式指定参数名称后跟=
来将第5个参数设置为第二个参数。 这样生活更轻松!
The toString() is implicitly created and prints the argument names and labels for the instance as shown below.
toString()是隐式创建的,并打印实例的参数名称和标签,如下所示。
data class Book(var name: String, var authorName: String = "Anupam", var lastModified: Long = 1234567, var rating: Float = 5f, var downloads: Int = 1000)
fun main(args: Array) {
var book = Book("Android tutorials","Anupam", 1234567, 4.5f, 1000)
println(book)
book = Book("Kotlin")
println(book)
book = Book("Swift",downloads = 500)
println(book)
book = Book("Java","Pankaj",rating = 5f, downloads = 1000)
println(book.toString())
book = Book("Python","Shubham",rating = 5f)
println(book.toString())
}
//Following is printed in the console.
//Book(name=Android tutorials, authorName=Anupam, lastModified=1234567, rating=4.5, downloads=1000)
//Book(name=Kotlin, authorName=Anupam, lastModified=1234567, rating=5.0, downloads=1000)
//Book(name=Swift, authorName=Anupam, lastModified=1234567, rating=5.0, downloads=500)
//Book(name=Java, authorName=Pankaj, lastModified=1234567, rating=5.0, downloads=1000)
//Book(name=Python, authorName=Shubham, lastModified=1234567, rating=5.0, downloads=1000)
Note: print
function implicitly adds a toString().
注意 : print
函数隐式添加一个toString()。
Copy function is used to create a copy of an instance of the data class with few of the properties modified.
复制功能用于创建数据类实例的副本,而很少修改属性。
It’s recommended to use val parameters in a data classes constructor in order to use immutable properties of an instances. Immutable objects are easier while working with multi-threaded applications.
建议在数据类构造函数中使用val参数,以使用实例的不可变属性。 使用多线程应用程序时,不可变对象更加容易。
Hence to create a copy of a immutable object by changing only few of the properties, copy()
function is handy.
因此,通过仅更改少量属性来创建不可变对象的copy()
, copy()
函数非常方便。
data class Book(val name: String, val authorName: String = "Anupam", val lastModified: Long = 1234567, val rating: Float = 5f, val downloads: Int = 1000)
fun main(args: Array) {
val book = Book("Android tutorials","Anupam", 1234567, 4.5f, 1000)
println(book)
val newBook = book.copy(name = "Kotlin")
println(newBook)
}
//Following is printed in the console.
//Book(name=Android tutorials, authorName=Anupam, lastModified=1234567, rating=4.5, downloads=1000)
//Book(name=Kotlin, authorName=Anupam, lastModified=1234567, rating=4.5, downloads=1000)
The hashCode()
method returns hash code for the object. If two objects are equal, hashCode()
produces the same integer result. Hence, equals()
returns true if the hashCode()
is equal, else it returns a false.
hashCode()
方法返回对象的哈希码。 如果两个对象相等,则hashCode()
会产生相同的整数结果。 因此,如果hashCode()
相等,则equals()
返回true,否则返回false。
data class Book(val name: String, val authorName: String = "Anupam", val lastModified: Long = 1234567, val rating: Float = 5f, val downloads: Int = 1000)
fun main(args: Array) {
val book = Book("Android tutorials","Anupam", 1234567, 4.5f, 1000)
println("Hashcode is ${book.hashCode()}")
val newBook = book.copy(name = "Kotlin")
println("Hashcode is ${newBook.hashCode()}")
val copyBook = book.copy()
println("Hashcode is ${copyBook.hashCode()}")
if(copyBook.equals(book))
println("copyBook and book are equal")
if(!book.equals(newBook))
println("newBook and book are NOT equal")
}
//Following is printed in the console.
//Hashcode is 649213087
//Hashcode is 1237165820
//Hashcode is 649213087
//copyBook and book are equal
//newBook and book are NOT equal
The first and third object hashcodes are equal hence they are equal.
第一和第三对象哈希码相等,因此它们相等。
Note: The equals()
method is equivalent to ==
in kotlin.
注意 : equals()
方法等效于kotlin中的==
。
componentN()
function lets us access each of the arguments specified in the constructor, in the order specified. N is the number of parameters in the constructor.
componentN()
函数使我们可以按指定的顺序访问构造函数中指定的每个参数。 N是构造函数中的参数数。
data class Book(val name: String, val authorName: String = "Anupam", val lastModified: Long = 1234567, val rating: Float = 5f, val downloads: Int = 1000)
fun main(args: Array) {
val book = Book("Android tutorials","Anupam", 1234567, 4.5f, 1000)
println(book.component1()) //Android tutorials
println(book.component2()) //Anupam
println(book.component3()) //1234567
println(book.component4()) //4.5
println(book.component5()) //1000
}
Destructuring declarations allows us to access the arguments as properties from the class object as shown below.
解构声明使我们可以从类对象访问参数作为属性,如下所示。
data class Book(val name: String, val authorName: String = "Anupam", val lastModified: Long = 1234567, val rating: Float = 5f, val downloads: Int = 1000)
fun main(args: Array) {
val book = Book("Android tutorials","Anupam", 1234567, 4.5f, 1000)
val (n,a,date,rating,downloads) = book
}
Note: If a visibility modifier such as private is set on any of the arguments, it can’t be accessed in the above function.
注意 :如果在任何参数上设置了可见性修饰符(例如private),则无法在上述函数中访问它。
data class Book(val name: String,private val authorName: String = "Anupam", val lastModified: Long = 1234567, val rating: Float = 5f, val downloads: Int = 1000)
fun main(args: Array) {
val book = Book("Android tutorials","Anupam", 1234567, 4.5f, 1000)
val (n,a,date,rating,downloads) = book //This won't compile since authorName is private
}
That’s all for quick roundup on Kotlin Data Classes.
这就是快速汇总Kotlin数据类的全部内容。
References: Kotlin Docs
参考: Kotlin Docs
翻译自: https://www.journaldev.com/18594/kotlin-data-class
kotlin数据类