Kotlin数据类

时间:2020-02-23 14:37:29  来源:igfitidea点击:

在本教程中,我们将研究Kotlin数据类。

Kotlin数据类

您是否厌倦了用Java为POJO数据类编写数千行代码?

每个Java程序员在某个阶段都必须记下他们为只需要存储一些数据的类需要编写的代码行数。
让我们看看Book.javaPOJO类的样子:

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 +
              '}';
  }
}

哇!这是96行代码,仅在一个对象中存储5个字段。
除了使用getter设置器,toString()equals()hashCode()方法外,我们在这里没有做太多其他事情。

在我们的实践中使用干净的体系结构和代码实践的分离之后,我们需要创建POJO类,因为每个项目都需要将数据存储在某个地方。
这可以增加样板代码。

这就是Kotlin使用数据类进行救援的地方。

数据类是Kotlin减少样板代码的答案。

上面的POJO类可以通过以下方式用Kotlin编写:

data class Book(var name: String, var authorName: String, var lastModified: Long, var rating: Float, var downloads: Int)

Kotlin将96行的Java代码转换为单行代码。

这是Kotlin减少项目中样板代码的方法!

创建Kotlin数据类

以下是创建Kotlin Data类的要求。

  • 您需要在类中添加关键字data

  • 主构造函数需要至少具有一个参数。

  • 主构造函数的每个参数都必须分配一个val或者var。

普通类不是这种情况,在普通类中,不必指定val或者var。

  • 数据类不能附加"抽象","打开","密封"或者"内部"

Kotlin Data Class内置方法

Kotlin Data类会自动为您创建以下功能。

  • equals()和hashCode()

  • toString()的形式为" Book(name = theitroad,authorName = Anupam)""

  • componentN()以指定的顺序对每个参数起作用。
    这称为解构声明。

  • copy()

Kotlin数据类功能

以下是数据类提供的一些功能。

  • 要创建无参数构造函数,请为主要构造函数中存在的每个参数指定默认值。

  • 数据类允许子类化(无需提及关键字" open")。

  • 您可以为函数equals(),hashCode()和toString()提供显式的实现。

  • 不允许对copy()和componentN()函数进行显式实现。

  • 我们可以通过在构造函数中指定可见性修饰符来控制getter和setter的可见性,如下所示。

  • val参数不会隐式定义setter(也不能明确定义!)。

数据类中的默认参数和命名参数

以下是我们的数据类:

data class Book(var name: String,private var authorName: String, var lastModified: Long, var rating: Float, var downloads: Int)

这些参数均未设置默认值。
因此,我们需要在实例化中为每个参数设置一个参数,如下所示。

data class Book(var name: String, var authorName: String, var lastModified: Long, var rating: Float, var downloads: Int)

让我们设置一些默认参数,看看实例化如何变化。

fun main(args: Array<String>) {
val book = Book("Android Tutorials","Anupam", 1234567, 4.5f, 1000)
}

除了设置每个参数,我们还可以使用命名参数仅设置非默认参数和我们希望设置的参数。
使用命名参数,我们可以通过显式指定参数名称后跟" ="来将第5个参数设置为第二个参数。
这样生活变得如此轻松!

Kotlin数据类toString()方法

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<String>) {
var book = Book("Android tutorials","Anupam", 1234567, 4.5f, 1000)

  book = Book("Kotlin")
  book = Book("Swift",downloads = 500)
  book = Book("Java","hyman",rating = 5f, downloads = 1000)
  book = Book("Python","Shubham",rating = 5f)

}

注意:print函数隐式添加一个toString()。

Kotlin数据类copy()方法

复制功能用于创建数据类实例的副本,而很少修改属性。

建议使用数据类构造函数中的val参数,以使用实例的不可变属性。
使用多线程应用程序时,不可变对象更加容易。

因此,通过仅更改少量属性来创建不可变对象的副本,可以使用copy()函数。

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<String>) {

  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","hyman",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=hyman, lastModified=1234567, rating=5.0, downloads=1000)
//Book(name=Python, authorName=Shubham, lastModified=1234567, rating=5.0, downloads=1000)

Kotlin数据类equals()和hashCode()

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<String>) {

  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)

第一和第三对象哈希码相等,因此它们相等。

注意:equals()方法等效于kotlin中的==。

销毁声明

通过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<String>) {

  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

解构声明使我们可以从类对象中将参数作为属性访问,如下所示。

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<String>) {

  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
  
}

注意:如果在任何参数上设置了可见性修饰符(例如private),则无法在上述函数中访问它。

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<String>) {

  val book = Book("Android tutorials","Anupam", 1234567, 4.5f, 1000)
  val (n,a,date,rating,downloads) = book
}