SlideShare a Scribd company logo
Kotlin Data Model
黃千碩 (Kros)
oSolve, Ltd./打⼯工趣
Mobile App Developer
Outline
• Android data model 演化史
• Kotlin 介紹
• Kotlin classes/data classes 介紹
• Kotlin companion object 介紹
• Unit testing
• What’s next?
Data Model 演化史
• 當第⼀一次在 Android 上寫 data model 時
Data Model 演化史
• 定義 property
public class User {

private String name;

private String email;


private int age;



private Date createdAt;

}
Data Model 演化史
• 定義 property
• ⼿手動實作 get, set
Data Model 演化史
• 定義 property
• ⼿手動實作 get, set
Data Model 演化史
• 定義 property
• ⼿手動實作 get, set
• IDE 可以幫忙產⽣生 setter, getter
Data Model 演化史
• 定義 property
• ⼿手動實作 get, set
• IDE 可以幫忙產⽣生 setter, getter, equal, hash, toString
public class User implements Parcelable {

private String name;



private String email;



private int age;



private Date createdAt;



@Override

public int hashCode() {

int result = name != null ? name.hashCode() : 0;

result = 31 * result + (email != null ? email.hashCode() : 0);

result = 31 * result + age;

result = 31 * result + (createdAt != null ? createdAt.hashCode() : 0);

return result;

}



@Override

public boolean equals(Object o) {

if (this == o) return true;

if (o == null || getClass() != o.getClass()) return false;



User user = (User) o;



if (age != user.age) return false;

if (name != null ? !name.equals(user.name) : user.name != null) return false;

if (email != null ? !email.equals(user.email) : user.email != null) return false;

return createdAt != null ? createdAt.equals(user.createdAt) : user.createdAt == null;



}



@Override

public String toString() {

return "User{" +

"name='" + name + ''' +

", email='" + email + ''' +

", age=" + age +

", createdAt=" + createdAt +

'}';

}



public String getName() {

return name;

}



public void setName(String name) {

this.name = name;

}



public String getEmail() {

return email;

}



public void setEmail(String email) {

this.email = email;

}



public int getAge() {

return age;

}



public void setAge(int age) {

this.age = age;

}



public Date getCreatedAt() {

return createdAt;

}



public void setCreatedAt(Date createdAt) {

this.createdAt = createdAt;

}
Parcelable
• 遇到 parcelable
Parcelable
• 遇到 parcelable
• ⼿手動實作
Parcelable
• 遇到 parcelable
• ⼿手動實作
Parcelable
• 遇到 parcelable
• ⼿手動實作
• ⽤用 android studio plugin 產⽣生 parcelable 實作
public class User implements Parcelable {

private String name;



private String email;



private int age;



private Date createdAt;



@Override

public int hashCode() {

int result = name != null ? name.hashCode() : 0;

result = 31 * result + (email != null ? email.hashCode() : 0);

result = 31 * result + age;

result = 31 * result + (createdAt != null ? createdAt.hashCode() : 0);

return result;

}



@Override

public boolean equals(Object o) {

if (this == o) return true;

if (o == null || getClass() != o.getClass()) return false;



User user = (User) o;



if (age != user.age) return false;

if (name != null ? !name.equals(user.name) : user.name != null) return false;

if (email != null ? !email.equals(user.email) : user.email != null) return false;

return createdAt != null ? createdAt.equals(user.createdAt) : user.createdAt == null;



}



@Override

public String toString() {

return "User{" +

"name='" + name + ''' +

", email='" + email + ''' +

", age=" + age +

", createdAt=" + createdAt +

'}';

}



public String getName() {

return name;

}



public void setName(String name) {

this.name = name;

}



public String getEmail() {

return email;

}



public void setEmail(String email) {

this.email = email;

}



public int getAge() {

return age;

}



public void setAge(int age) {

this.age = age;

}



public Date getCreatedAt() {

return createdAt;

}



public void setCreatedAt(Date createdAt) {

this.createdAt = createdAt;

}



@Override

public int describeContents() { return 0; }



@Override

public void writeToParcel(Parcel dest, int flags) {

dest.writeString(this.name);

dest.writeString(this.email);

dest.writeInt(this.age);

dest.writeLong(this.createdAt != null ? this.createdAt.getTime() : -1);

}



public User() {}



protected User(Parcel in) {

this.name = in.readString();

this.email = in.readString();

this.age = in.readInt();

long tmpCreatedAt = in.readLong();

this.createdAt = tmpCreatedAt == -1 ? null : new Date(tmpCreatedAt);

}



public static final Creator<User> CREATOR = new Creator<User>() {

@Override

public User createFromParcel(Parcel source) {return new User(source);}



@Override

public User[] newArray(int size) {return new User[size];}

};

public class User implements Parcelable {

private String name;



private String email;



private int age;



private Date createdAt;



@Override

public int hashCode() {

int result = name != null ? name.hashCode() : 0;

result = 31 * result + (email != null ? email.hashCode() : 0);

result = 31 * result + age;

result = 31 * result + (createdAt != null ? createdAt.hashCode() : 0);

return result;

}



@Override

public boolean equals(Object o) {

if (this == o) return true;

if (o == null || getClass() != o.getClass()) return false;



User user = (User) o;



if (age != user.age) return false;

if (name != null ? !name.equals(user.name) : user.name != null) return false;

if (email != null ? !email.equals(user.email) : user.email != null) return false;

return createdAt != null ? createdAt.equals(user.createdAt) : user.createdAt == null;



}



@Override

public String toString() {

return "User{" +

"name='" + name + ''' +

", email='" + email + ''' +

", age=" + age +

", createdAt=" + createdAt +

'}';

}



public String getName() {

return name;

}



public void setName(String name) {

this.name = name;

}



public String getEmail() {

return email;

}



public void setEmail(String email) {

this.email = email;

}



public int getAge() {

return age;

}



public void setAge(int age) {

this.age = age;

}



public Date getCreatedAt() {

return createdAt;

}



public void setCreatedAt(Date createdAt) {

this.createdAt = createdAt;

}



@Override

public int describeContents() { return 0; }



@Override

public void writeToParcel(Parcel dest, int flags) {

dest.writeString(this.name);

dest.writeString(this.email);

dest.writeInt(this.age);

dest.writeLong(this.createdAt != null ? this.createdAt.getTime() : -1);

}



public User() {}



protected User(Parcel in) {

this.name = in.readString();

this.email = in.readString();

this.age = in.readInt();

long tmpCreatedAt = in.readLong();

this.createdAt = tmpCreatedAt == -1 ? null : new Date(tmpCreatedAt);

}



public static final Creator<User> CREATOR = new Creator<User>() {

@Override

public User createFromParcel(Parcel source) {return new User(source);}



@Override

public User[] newArray(int size) {return new User[size];}

};

隨隨便便便便就超過 100 ⾏行行
Parcelable
• 遇到 parcelable
• ⼿手動實作
• ⽤用 plugin 產⽣生 Parcelable 實作
• 當 class 越來來越多,property 越來來越多,開發的⼈人越來來越多
• 每次實作就成了了問題
願望
• 如果可以這⼀一切可以⾃自動產⽣生就好!
Libraries
• Google AutoValue

https://github.com/google/auto
• Lombok

https://github.com/rzwitserloot/lombok

AutoValue
• 只要定義好 interface,就會⾃自動產⽣生 model
• ⾃自動產⽣生 setter, getter, equal, hash, toString
• 有 plugin ⾃自動產⽣生 parcelable 實作
• Builder pattern
@AutoValue

public abstract class User implements Parcelable {



public abstract String name();



@Nullable

public abstract String email();



public abstract int age();



public abstract Date createdAt();



public static User create(String name, String email, int age, Date createdAt) {

return builder()

.name(name)

.email(email)

.age(age)

.createdAt(createdAt)

.build();

}



public static Builder builder() {return new AutoValue_User.Builder();}



@AutoValue.Builder

public abstract static class Builder {



public abstract Builder name(String name);



public abstract Builder email(String email);



public abstract Builder age(int age);



public abstract Builder createdAt(Date createdAt);



public abstract User build();

}

}
AutoValue
• 除此之外,加入兩兩個概念念:
• Immutable Object: 預設產⽣生的 object 都是 value object,沒有
setter,只有 getter
• Null-safety: 每個 property 都需定義 NonNull, Nullable
@AutoValue

public abstract class User implements Parcelable {



public abstract String name();



@Nullable

public abstract String email();



public abstract int age();



public abstract Date createdAt();



public static User create(String name, String email, int age, Date createdAt) {

return builder()

.name(name)

.email(email)

.age(age)

.createdAt(createdAt)

.build();

}



public static Builder builder() {return new AutoValue_User.Builder();}



@AutoValue.Builder

public abstract static class Builder {



public abstract Builder name(String name);



public abstract Builder email(String email);



public abstract Builder age(int age);



public abstract Builder createdAt(Date createdAt);



public abstract User build();

}

}
Kotlin 介紹
val name: String = "Android"
Kotlin 介紹
val name: String = "Android"
val email: String? = null
Kotlin 介紹
val name: String = "Android"
val email: String? = null
var name: String = "Android"
Kotlin 介紹
val name: String = "Android"
val email: String? = null
var name: String = "Android"

name = "Android Taipei"
Kotlin 介紹
val name: String = "Android"
val email: String? = null
var name: String = "Android"

name = "Android Taipei"
• val: Assign-once (read-only) local variable
• var: Mutable variable:
Kotlin 介紹
fun doSomething(name: String) : String {
return name.toUpperCase()
}
Classes
• 如何定義⼀一個 class
class User {
}
class User constructor(

name: String,
email: String?,

age: Int,

createdAt: Date

) { }
• 定義 constructor
class User(

name: String,
email: String?,

age: Int,

createdAt: Date

) { }
• 可以省略略關鍵字
class User(

name: String,
email: String?,

age: Int,

createdAt: Date

) {
var name: String = name,
var email: String? = email,

var age: Int = age,

var createdAt: Date = createdAt
}
• 定義 properties
class User(

var name: String,
var email: String?,

var age: Int,

var createdAt: Date

) { }
• 更更簡單的寫法
class User(

val name: String,
val email: String?,

val age: Int,

val createdAt: Date

) { }
• 定義 immutable properties
class User(

val name: String = "No Name",
val email: String? = null,

val age: Int = 0,

val createdAt: Date = Date()

) { }
• 給預設值
Data Classes
• The compiler automatically derives the following members from all
properties declared in the primary constructor:
• 根據你定義的 properties,⾃自動幫你產⽣生以下四種內容
• equals()/hashCode()
• toString()
• componentN() functions
• copy()
Data Classes
• Primary constructor ⾄至少要有⼀一個參參數
• 參參數只能是 val, var
class User (

val name: String,
val email: String?,

val age: Int,

val createdAt: Date

) { }
data class User(

val name: String,
val email: String?,

val age: Int,

val createdAt: Date

) { }
Parcelable
• 當然也有開發者提供 parcelable 的 plugin,⾃自動產⽣生 parcelable 實作
data class User(

val name: String,
val email: String?,

val age: Int,

val createdAt: Date

) { }
data class User(

val name: String,
val email: String?,

val age: Int,

val createdAt: Date

) : AutoParcelable { }
演化比較
data class User(

val name: String,
val email: String?,

val age: Int,

val createdAt: Date

) : AutoParcelable { }
public class User implements Parcelable {

private String name;



private String email;



private int age;



private Date createdAt;



@Override

public int hashCode() {

int result = name != null ? name.hashCode() : 0;

result = 31 * result + (email != null ? email.hashCode() : 0);

result = 31 * result + age;

result = 31 * result + (createdAt != null ? createdAt.hashCode() : 0);

return result;

}



@Override

public boolean equals(Object o) {

if (this == o) return true;

if (o == null || getClass() != o.getClass()) return false;



User user = (User) o;



if (age != user.age) return false;

if (name != null ? !name.equals(user.name) : user.name != null) return false;

if (email != null ? !email.equals(user.email) : user.email != null) return false;

return createdAt != null ? createdAt.equals(user.createdAt) : user.createdAt == null;



}



@Override

public String toString() {

return "User{" +

"name='" + name + ''' +

", email='" + email + ''' +

", age=" + age +

", createdAt=" + createdAt +

'}';

}



public String getName() {

return name;

}



public void setName(String name) {

this.name = name;

}



public String getEmail() {

return email;

}



public void setEmail(String email) {

this.email = email;

}



public int getAge() {

return age;

}



public void setAge(int age) {

this.age = age;

}



public Date getCreatedAt() {

return createdAt;

}



public void setCreatedAt(Date createdAt) {

this.createdAt = createdAt;

}



@Override

public int describeContents() { return 0; }



@Override

public void writeToParcel(Parcel dest, int flags) {

dest.writeString(this.name);

dest.writeString(this.email);

dest.writeInt(this.age);

dest.writeLong(this.createdAt != null ? this.createdAt.getTime() : -1);

}



public User() {}



protected User(Parcel in) {

this.name = in.readString();

this.email = in.readString();

this.age = in.readInt();

long tmpCreatedAt = in.readLong();

this.createdAt = tmpCreatedAt == -1 ? null : new Date(tmpCreatedAt);

}



public static final Creator<User> CREATOR = new Creator<User>() {

@Override

public User createFromParcel(Parcel source) {return new User(source);}



@Override

public User[] newArray(int size) {return new User[size];}

};

@AutoValue

public abstract class User implements Parcelable {



public abstract String name();



@Nullable

public abstract String email();



public abstract int age();



public abstract Date createdAt();



public static User create(String name, String email, int age, Date createdAt) {

return builder()

.name(name)

.email(email)

.age(age)

.createdAt(createdAt)

.build();

}



public static Builder builder() {return new AutoValue_User.Builder();}



@AutoValue.Builder

public abstract static class Builder {



public abstract Builder name(String name);



public abstract Builder email(String email);



public abstract Builder age(int age);



public abstract Builder createdAt(Date createdAt);



public abstract User build();

}

}
Copy
• 很多時候我們會更更新 object 內容
• 如何更更新⼀一個 immutable object?
• 利利⽤用 copy()
class User(

val name: String,
val email: String?

) {
}
class User(

val name: String,
val email: String?

) {
fun copy(name: String = this.name, email: String? = this.email): User {

return User(name = name, email = email)

}
}
• copy() 的實作如下
data class User(

val name: String,
val email: String?,

val age: Int,

val createdAt: Date

) : AutoParcelable { }
data class User(

val name: String,

val email: String?,

val age: Int,

val createdAt: Date

) : AutoParcelable {

fun updateAge(newAge: Int): User {

return copy(age = newAge)

}

}
data class User(

val name: String,

val email: String?,

val age: Int,

val createdAt: Date

) : AutoParcelable {

fun updateAge(newAge: Int): User {

return copy(age = newAge)

}

}
data class User(

val name: String,

val email: String?,

val age: Int,

val createdAt: Date

) : AutoParcelable {

fun updateAge(newAge: Int): User {

return copy(age = newAge)

}

}
user = user.updateAge(18);

assertThat(user.getAge()).isEqualTo(18);
Companion Object
• Kotlin 中沒有 static 的概念念,改⽤用 Companion Object
Companion Object
• Kotlin 中沒有 static 的概念念,改⽤用 Companion Object
• Static method -> Companion method
class User(

val name: String,
val email: String?

) {
}
class User(

val name: String,
val email: String?

) {
companion object {

fun myCompanionMethod() {

// ...

}

}
}
class User(

val name: String,
val email: String?

) {
companion object {

fun myCompanionMethod() {

// ...

}

}
}
// Java 中使⽤用
User.Companion.myCompanionMethod();
Companion Object
• Kotlin 中沒有 static 的概念念,改⽤用 Companion Object
• Static method -> companion method
• 舉例例:ViewModel (MVVM 中的 ViewModel)
User user = ... // age = 50
UserViewModel viewModel = createViewModel(user)
viewModel.getAgeString(); // "50 歲"
class UserViewModel(

context: Context,

val user: User

) {
}
class UserViewModel(

context: Context,

val user: User

) {

val ageString: String

}
class UserViewModel(

context: Context,

val user: User

) {

val ageString: String



init {

ageString = context.getString(R.string.age_is, user.age.toString())

}

}
class UserViewModel(

context: Context,

val user: User

) {

val ageString: String



init {

ageString = context.getString(R.string.age_is, user.age.toString())

}

}
UserViewModel viewModel = new UserViewModel(context, user);
viewModel.getAgeString(); // “50 歲"
Companion Object
• 想要使⽤用 data classes
• 使⽤用 companion method
data class UserViewModel(

val user: User,

val ageString: String

) {


}
data class UserViewModel(

val user: User,

val ageString: String

) {

companion object {

fun create(context: Context, user: User): UserViewModel {

val ageString = context.getString(R.string.age_is, user.age.toString())

return UserViewModel(user, ageString)

}

}

}
data class UserViewModel(

val user: User,

val ageString: String

) {

companion object {

fun create(context: Context, user: User): UserViewModel {

val ageString = context.getString(R.string.age_is, user.age.toString())

return UserViewModel(user, ageString)

}

}

}
Private Constructor
• 與 Java 相同,可以 private constructor,讓維護更更容易易
data class UserViewModel(

val user: User,

val ageString: String

) {

companion object {

fun create(context: Context, user: User): UserViewModel {

val ageString = context.getString(R.string.age_is, user.age.toString())

return UserViewModel(user, ageString)

}

}

}
data class UserViewModel private constructor(

val user: User,

val ageString: String

) {

companion object {

fun create(context: Context, user: User): UserViewModel {

val ageString = context.getString(R.string.age_is, user.age.toString())

return UserViewModel(user, ageString)

}

}

}
data class UserViewModel private constructor(

val user: User,

val ageString: String

) {

companion object {

fun create(context: Context, user: User): UserViewModel {

val ageString = context.getString(R.string.age_is, user.age.toString())

return UserViewModel(user, ageString)

}

}

}
// Java 中使⽤用
new UserViewModel();
data class UserViewModel private constructor(

val user: User,

val ageString: String

) {

companion object {

fun create(context: Context, user: User): UserViewModel {

val ageString = context.getString(R.string.age_is, user.age.toString())

return UserViewModel(user, ageString)

}

}

}
// Java 中使⽤用
new UserViewModel();
data class UserViewModel private constructor(

val user: User,

val ageString: String

) {

companion object {

fun create(context: Context, user: User): UserViewModel {

val ageString = context.getString(R.string.age_is, user.age.toString())

return UserViewModel(user, ageString)

}

}

}
// Java 中使⽤用
new UserViewModel();
UserViewModel viewModel = UserViewModel.Companion.create(context, user);
data class UserViewModel private constructor(

val user: User,

val ageString: String

) {

companion object {

fun create(context: Context, user: User): UserViewModel {

val ageString = context.getString(R.string.age_is, user.age.toString())

return UserViewModel(user, ageString)

}

}

}
// Java 中使⽤用
new UserViewModel();
UserViewModel viewModel = UserViewModel.Companion.create(context, user);
viewModel.getAgeString(); // "50 歲"
Unit Test
• Kotlin 所有的東⻄西,預設都是 final
Unit Test
• Kotlin 所有的東⻄西,預設都是 final
• 當要 Mock (2.0) 時,會出現以下問題:
org.mockito.exceptions.base.MockitoException: 

Cannot mock/spy class com.example.kotlindataclass.model.xxx
cannot mock/spy because :

- final class
Solution
• 啟動 Mockito 2 的 option 功能 

(opt-in mocking of final classes/methods)
• 在路路徑 test/resources/mockito-extensions 底下新增檔案:

org.mockito.plugins.MockMaker
• 檔案內容:

mock-maker-inline
Solution
如何開始導入 Kotlin
1.挑選最少⽤用到的 Data Model
2.對此 Data Model 寫測試 (encode/decode)
3.透過 Android Studio Converter (command+shift+a)
4.在⼀一個 commit 裡⼀一次做完 (要反悔悔也容易易)
What’s Next
• ViewModel 採⽤用 Kotlin
• Presenter 採⽤用 Kotlin
• Helper 採⽤用 Kotlin
• View 採⽤用 Kotlin
• …
What’s Next
• 資料操作
• Collections: List, Set, Map
• map, filter, find…etc.
• more…
Using Kotlin for Android today!
Reference
• Kotlin Data Classes

https://kotlinlang.org/docs/reference/data-classes.html
• Kotlin 的 data class 會對你的程式產⽣生什什麼樣的化學反應

https://ingramchen.io/blog/2017/06/kotlin-data-class.html
• Kotlin Koans

https://kotlinlang.org/docs/tutorials/koans.html
• Mock the unmockable

https://github.com/mockito/mockito/wiki/What%27s-new-in-
Mockito-2#mock-the-unmockable-opt-in-mocking-of-final-classesmethods


More Related Content

What's hot

Cloud computing BI publication 1
Cloud computing BI   publication 1Cloud computing BI   publication 1
Cloud computing BI publication 1Jobe Bacwadi
 
Why realm?
Why realm?Why realm?
Android Developer Toolbox 2017
Android Developer Toolbox 2017Android Developer Toolbox 2017
Android Developer Toolbox 2017
Shem Magnezi
 
#살아있다 #자프링외길12년차 #코프링2개월생존기
#살아있다 #자프링외길12년차 #코프링2개월생존기#살아있다 #자프링외길12년차 #코프링2개월생존기
#살아있다 #자프링외길12년차 #코프링2개월생존기
Arawn Park
 
JavaScript Fundamentals with Angular and Lodash
JavaScript Fundamentals with Angular and LodashJavaScript Fundamentals with Angular and Lodash
JavaScript Fundamentals with Angular and Lodash
Bret Little
 
ITK Tutorial Presentation Slides-948
ITK Tutorial Presentation Slides-948ITK Tutorial Presentation Slides-948
ITK Tutorial Presentation Slides-948
Kitware Kitware
 
DevNation'15 - Using Lambda Expressions to Query a Datastore
DevNation'15 - Using Lambda Expressions to Query a DatastoreDevNation'15 - Using Lambda Expressions to Query a Datastore
DevNation'15 - Using Lambda Expressions to Query a Datastore
Xavier Coulon
 
Chaining and function composition with lodash / underscore
Chaining and function composition with lodash / underscoreChaining and function composition with lodash / underscore
Chaining and function composition with lodash / underscore
Nicolas Carlo
 
Windows Phone Launchers and Choosers
Windows Phone Launchers and ChoosersWindows Phone Launchers and Choosers
Easy Scaling with Open Source Data Structures, by Talip Ozturk
Easy Scaling with Open Source Data Structures, by Talip OzturkEasy Scaling with Open Source Data Structures, by Talip Ozturk
Easy Scaling with Open Source Data Structures, by Talip OzturkZeroTurnaround
 
Basic java, java collection Framework and Date Time API
Basic java, java collection Framework and Date Time APIBasic java, java collection Framework and Date Time API
Basic java, java collection Framework and Date Time API
jagriti srivastava
 
Graphql, REST and Apollo
Graphql, REST and ApolloGraphql, REST and Apollo
Graphql, REST and Apollo
Christoffer Noring
 
Java script objects 1
Java script objects 1Java script objects 1
Java script objects 1H K
 
20160616技術會議
20160616技術會議20160616技術會議
20160616技術會議
Jason Kuan
 
Java весна 2013 лекция 5
Java весна 2013 лекция 5Java весна 2013 лекция 5
Java весна 2013 лекция 5Technopark
 
[2019-07] GraphQL in depth (serverside)
[2019-07] GraphQL in depth (serverside)[2019-07] GraphQL in depth (serverside)
[2019-07] GraphQL in depth (serverside)
croquiscom
 
Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...
Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...
Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...
Domenic Denicola
 
The Ring programming language version 1.5.1 book - Part 36 of 180
The Ring programming language version 1.5.1 book - Part 36 of 180The Ring programming language version 1.5.1 book - Part 36 of 180
The Ring programming language version 1.5.1 book - Part 36 of 180
Mahmoud Samir Fayed
 
UIKonf App & Data Driven Design @swift.berlin
UIKonf App & Data Driven Design @swift.berlinUIKonf App & Data Driven Design @swift.berlin
UIKonf App & Data Driven Design @swift.berlin
Maxim Zaks
 

What's hot (20)

Green dao
Green daoGreen dao
Green dao
 
Cloud computing BI publication 1
Cloud computing BI   publication 1Cloud computing BI   publication 1
Cloud computing BI publication 1
 
Why realm?
Why realm?Why realm?
Why realm?
 
Android Developer Toolbox 2017
Android Developer Toolbox 2017Android Developer Toolbox 2017
Android Developer Toolbox 2017
 
#살아있다 #자프링외길12년차 #코프링2개월생존기
#살아있다 #자프링외길12년차 #코프링2개월생존기#살아있다 #자프링외길12년차 #코프링2개월생존기
#살아있다 #자프링외길12년차 #코프링2개월생존기
 
JavaScript Fundamentals with Angular and Lodash
JavaScript Fundamentals with Angular and LodashJavaScript Fundamentals with Angular and Lodash
JavaScript Fundamentals with Angular and Lodash
 
ITK Tutorial Presentation Slides-948
ITK Tutorial Presentation Slides-948ITK Tutorial Presentation Slides-948
ITK Tutorial Presentation Slides-948
 
DevNation'15 - Using Lambda Expressions to Query a Datastore
DevNation'15 - Using Lambda Expressions to Query a DatastoreDevNation'15 - Using Lambda Expressions to Query a Datastore
DevNation'15 - Using Lambda Expressions to Query a Datastore
 
Chaining and function composition with lodash / underscore
Chaining and function composition with lodash / underscoreChaining and function composition with lodash / underscore
Chaining and function composition with lodash / underscore
 
Windows Phone Launchers and Choosers
Windows Phone Launchers and ChoosersWindows Phone Launchers and Choosers
Windows Phone Launchers and Choosers
 
Easy Scaling with Open Source Data Structures, by Talip Ozturk
Easy Scaling with Open Source Data Structures, by Talip OzturkEasy Scaling with Open Source Data Structures, by Talip Ozturk
Easy Scaling with Open Source Data Structures, by Talip Ozturk
 
Basic java, java collection Framework and Date Time API
Basic java, java collection Framework and Date Time APIBasic java, java collection Framework and Date Time API
Basic java, java collection Framework and Date Time API
 
Graphql, REST and Apollo
Graphql, REST and ApolloGraphql, REST and Apollo
Graphql, REST and Apollo
 
Java script objects 1
Java script objects 1Java script objects 1
Java script objects 1
 
20160616技術會議
20160616技術會議20160616技術會議
20160616技術會議
 
Java весна 2013 лекция 5
Java весна 2013 лекция 5Java весна 2013 лекция 5
Java весна 2013 лекция 5
 
[2019-07] GraphQL in depth (serverside)
[2019-07] GraphQL in depth (serverside)[2019-07] GraphQL in depth (serverside)
[2019-07] GraphQL in depth (serverside)
 
Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...
Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...
Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...
 
The Ring programming language version 1.5.1 book - Part 36 of 180
The Ring programming language version 1.5.1 book - Part 36 of 180The Ring programming language version 1.5.1 book - Part 36 of 180
The Ring programming language version 1.5.1 book - Part 36 of 180
 
UIKonf App & Data Driven Design @swift.berlin
UIKonf App & Data Driven Design @swift.berlinUIKonf App & Data Driven Design @swift.berlin
UIKonf App & Data Driven Design @swift.berlin
 

Similar to Kotlin Data Model

First few months with Kotlin - Introduction through android examples
First few months with Kotlin - Introduction through android examplesFirst few months with Kotlin - Introduction through android examples
First few months with Kotlin - Introduction through android examples
Nebojša Vukšić
 
public class Person { private String name; private int age;.pdf
public class Person { private String name; private int age;.pdfpublic class Person { private String name; private int age;.pdf
public class Person { private String name; private int age;.pdf
arjuncp10
 
Creating a Facebook Clone - Part X.pdf
Creating a Facebook Clone - Part X.pdfCreating a Facebook Clone - Part X.pdf
Creating a Facebook Clone - Part X.pdf
ShaiAlmog1
 
C# 3.5 Features
C# 3.5 FeaturesC# 3.5 Features
@author public class Person{   String sname, .pdf
  @author   public class Person{   String sname, .pdf  @author   public class Person{   String sname, .pdf
@author public class Person{   String sname, .pdf
aplolomedicalstoremr
 
Code to copy Person.java .pdf
Code to copy Person.java .pdfCode to copy Person.java .pdf
Code to copy Person.java .pdf
anokhijew
 
Lombokの紹介
Lombokの紹介Lombokの紹介
Lombokの紹介
onozaty
 
Code Smells y Refactoring o haciendo que nuestro codigo huela (y se vea) mejo...
Code Smells y Refactoring o haciendo que nuestro codigo huela (y se vea) mejo...Code Smells y Refactoring o haciendo que nuestro codigo huela (y se vea) mejo...
Code Smells y Refactoring o haciendo que nuestro codigo huela (y se vea) mejo...
.NET Conf UY
 
AST Transformations at JFokus
AST Transformations at JFokusAST Transformations at JFokus
AST Transformations at JFokusHamletDRC
 
Speed up the mobile development process
Speed up the mobile development processSpeed up the mobile development process
Speed up the mobile development process
LeonardoSarra
 
Creating a Whatsapp Clone - Part XI.pdf
Creating a Whatsapp Clone - Part XI.pdfCreating a Whatsapp Clone - Part XI.pdf
Creating a Whatsapp Clone - Part XI.pdf
ShaiAlmog1
 
TDC2016POA | Trilha .NET - CQRS e ES na prática com RavenDB
TDC2016POA | Trilha .NET - CQRS e ES na prática com RavenDBTDC2016POA | Trilha .NET - CQRS e ES na prática com RavenDB
TDC2016POA | Trilha .NET - CQRS e ES na prática com RavenDB
tdc-globalcode
 
What's new in C# 6 - NetPonto Porto 20160116
What's new in C# 6  - NetPonto Porto 20160116What's new in C# 6  - NetPonto Porto 20160116
What's new in C# 6 - NetPonto Porto 20160116
Paulo Morgado
 
CodeCamp Iasi 10 march 2012 - Practical Groovy
CodeCamp Iasi 10 march 2012 - Practical GroovyCodeCamp Iasi 10 march 2012 - Practical Groovy
CodeCamp Iasi 10 march 2012 - Practical GroovyCodecamp Romania
 
Creating a Facebook Clone - Part XX.pdf
Creating a Facebook Clone - Part XX.pdfCreating a Facebook Clone - Part XX.pdf
Creating a Facebook Clone - Part XX.pdf
ShaiAlmog1
 
Requery overview
Requery overviewRequery overview
Requery overview
Sunghyouk Bae
 
Groovy Ast Transformations (greach)
Groovy Ast Transformations (greach)Groovy Ast Transformations (greach)
Groovy Ast Transformations (greach)
HamletDRC
 
Creating a Facebook Clone - Part XIX - Transcript.pdf
Creating a Facebook Clone - Part XIX - Transcript.pdfCreating a Facebook Clone - Part XIX - Transcript.pdf
Creating a Facebook Clone - Part XIX - Transcript.pdf
ShaiAlmog1
 
Create a Code that will add an Add, Edi, and Delete button to the GU.pdf
Create a Code that will add an Add, Edi, and Delete button to the GU.pdfCreate a Code that will add an Add, Edi, and Delete button to the GU.pdf
Create a Code that will add an Add, Edi, and Delete button to the GU.pdf
lakshmijewellery
 
Kotlin for android
Kotlin for androidKotlin for android
Kotlin for android
Ahmed Nabil
 

Similar to Kotlin Data Model (20)

First few months with Kotlin - Introduction through android examples
First few months with Kotlin - Introduction through android examplesFirst few months with Kotlin - Introduction through android examples
First few months with Kotlin - Introduction through android examples
 
public class Person { private String name; private int age;.pdf
public class Person { private String name; private int age;.pdfpublic class Person { private String name; private int age;.pdf
public class Person { private String name; private int age;.pdf
 
Creating a Facebook Clone - Part X.pdf
Creating a Facebook Clone - Part X.pdfCreating a Facebook Clone - Part X.pdf
Creating a Facebook Clone - Part X.pdf
 
C# 3.5 Features
C# 3.5 FeaturesC# 3.5 Features
C# 3.5 Features
 
@author public class Person{   String sname, .pdf
  @author   public class Person{   String sname, .pdf  @author   public class Person{   String sname, .pdf
@author public class Person{   String sname, .pdf
 
Code to copy Person.java .pdf
Code to copy Person.java .pdfCode to copy Person.java .pdf
Code to copy Person.java .pdf
 
Lombokの紹介
Lombokの紹介Lombokの紹介
Lombokの紹介
 
Code Smells y Refactoring o haciendo que nuestro codigo huela (y se vea) mejo...
Code Smells y Refactoring o haciendo que nuestro codigo huela (y se vea) mejo...Code Smells y Refactoring o haciendo que nuestro codigo huela (y se vea) mejo...
Code Smells y Refactoring o haciendo que nuestro codigo huela (y se vea) mejo...
 
AST Transformations at JFokus
AST Transformations at JFokusAST Transformations at JFokus
AST Transformations at JFokus
 
Speed up the mobile development process
Speed up the mobile development processSpeed up the mobile development process
Speed up the mobile development process
 
Creating a Whatsapp Clone - Part XI.pdf
Creating a Whatsapp Clone - Part XI.pdfCreating a Whatsapp Clone - Part XI.pdf
Creating a Whatsapp Clone - Part XI.pdf
 
TDC2016POA | Trilha .NET - CQRS e ES na prática com RavenDB
TDC2016POA | Trilha .NET - CQRS e ES na prática com RavenDBTDC2016POA | Trilha .NET - CQRS e ES na prática com RavenDB
TDC2016POA | Trilha .NET - CQRS e ES na prática com RavenDB
 
What's new in C# 6 - NetPonto Porto 20160116
What's new in C# 6  - NetPonto Porto 20160116What's new in C# 6  - NetPonto Porto 20160116
What's new in C# 6 - NetPonto Porto 20160116
 
CodeCamp Iasi 10 march 2012 - Practical Groovy
CodeCamp Iasi 10 march 2012 - Practical GroovyCodeCamp Iasi 10 march 2012 - Practical Groovy
CodeCamp Iasi 10 march 2012 - Practical Groovy
 
Creating a Facebook Clone - Part XX.pdf
Creating a Facebook Clone - Part XX.pdfCreating a Facebook Clone - Part XX.pdf
Creating a Facebook Clone - Part XX.pdf
 
Requery overview
Requery overviewRequery overview
Requery overview
 
Groovy Ast Transformations (greach)
Groovy Ast Transformations (greach)Groovy Ast Transformations (greach)
Groovy Ast Transformations (greach)
 
Creating a Facebook Clone - Part XIX - Transcript.pdf
Creating a Facebook Clone - Part XIX - Transcript.pdfCreating a Facebook Clone - Part XIX - Transcript.pdf
Creating a Facebook Clone - Part XIX - Transcript.pdf
 
Create a Code that will add an Add, Edi, and Delete button to the GU.pdf
Create a Code that will add an Add, Edi, and Delete button to the GU.pdfCreate a Code that will add an Add, Edi, and Delete button to the GU.pdf
Create a Code that will add an Add, Edi, and Delete button to the GU.pdf
 
Kotlin for android
Kotlin for androidKotlin for android
Kotlin for android
 

More from Kros Huang

Kotlin Receiver Types 介紹
Kotlin Receiver Types 介紹Kotlin Receiver Types 介紹
Kotlin Receiver Types 介紹
Kros Huang
 
Android MvRx Framework 介紹
Android MvRx Framework 介紹Android MvRx Framework 介紹
Android MvRx Framework 介紹
Kros Huang
 
Epoxy 介紹
Epoxy 介紹Epoxy 介紹
Epoxy 介紹
Kros Huang
 
Fastlane on Android 介紹
Fastlane on Android 介紹Fastlane on Android 介紹
Fastlane on Android 介紹
Kros Huang
 
RxJava 2.0 介紹
RxJava 2.0 介紹RxJava 2.0 介紹
RxJava 2.0 介紹
Kros Huang
 
Rxjava 介紹與 Android 中的 RxJava
Rxjava 介紹與 Android 中的 RxJavaRxjava 介紹與 Android 中的 RxJava
Rxjava 介紹與 Android 中的 RxJava
Kros Huang
 
Android with dagger_2
Android with dagger_2Android with dagger_2
Android with dagger_2
Kros Huang
 

More from Kros Huang (7)

Kotlin Receiver Types 介紹
Kotlin Receiver Types 介紹Kotlin Receiver Types 介紹
Kotlin Receiver Types 介紹
 
Android MvRx Framework 介紹
Android MvRx Framework 介紹Android MvRx Framework 介紹
Android MvRx Framework 介紹
 
Epoxy 介紹
Epoxy 介紹Epoxy 介紹
Epoxy 介紹
 
Fastlane on Android 介紹
Fastlane on Android 介紹Fastlane on Android 介紹
Fastlane on Android 介紹
 
RxJava 2.0 介紹
RxJava 2.0 介紹RxJava 2.0 介紹
RxJava 2.0 介紹
 
Rxjava 介紹與 Android 中的 RxJava
Rxjava 介紹與 Android 中的 RxJavaRxjava 介紹與 Android 中的 RxJava
Rxjava 介紹與 Android 中的 RxJava
 
Android with dagger_2
Android with dagger_2Android with dagger_2
Android with dagger_2
 

Recently uploaded

MCQ Soil mechanics questions (Soil shear strength).pdf
MCQ Soil mechanics questions (Soil shear strength).pdfMCQ Soil mechanics questions (Soil shear strength).pdf
MCQ Soil mechanics questions (Soil shear strength).pdf
Osamah Alsalih
 
Nuclear Power Economics and Structuring 2024
Nuclear Power Economics and Structuring 2024Nuclear Power Economics and Structuring 2024
Nuclear Power Economics and Structuring 2024
Massimo Talia
 
CME397 Surface Engineering- Professional Elective
CME397 Surface Engineering- Professional ElectiveCME397 Surface Engineering- Professional Elective
CME397 Surface Engineering- Professional Elective
karthi keyan
 
Fundamentals of Electric Drives and its applications.pptx
Fundamentals of Electric Drives and its applications.pptxFundamentals of Electric Drives and its applications.pptx
Fundamentals of Electric Drives and its applications.pptx
manasideore6
 
Unbalanced Three Phase Systems and circuits.pptx
Unbalanced Three Phase Systems and circuits.pptxUnbalanced Three Phase Systems and circuits.pptx
Unbalanced Three Phase Systems and circuits.pptx
ChristineTorrepenida1
 
Heap Sort (SS).ppt FOR ENGINEERING GRADUATES, BCA, MCA, MTECH, BSC STUDENTS
Heap Sort (SS).ppt FOR ENGINEERING GRADUATES, BCA, MCA, MTECH, BSC STUDENTSHeap Sort (SS).ppt FOR ENGINEERING GRADUATES, BCA, MCA, MTECH, BSC STUDENTS
Heap Sort (SS).ppt FOR ENGINEERING GRADUATES, BCA, MCA, MTECH, BSC STUDENTS
Soumen Santra
 
DESIGN A COTTON SEED SEPARATION MACHINE.docx
DESIGN A COTTON SEED SEPARATION MACHINE.docxDESIGN A COTTON SEED SEPARATION MACHINE.docx
DESIGN A COTTON SEED SEPARATION MACHINE.docx
FluxPrime1
 
Pile Foundation by Venkatesh Taduvai (Sub Geotechnical Engineering II)-conver...
Pile Foundation by Venkatesh Taduvai (Sub Geotechnical Engineering II)-conver...Pile Foundation by Venkatesh Taduvai (Sub Geotechnical Engineering II)-conver...
Pile Foundation by Venkatesh Taduvai (Sub Geotechnical Engineering II)-conver...
AJAYKUMARPUND1
 
CW RADAR, FMCW RADAR, FMCW ALTIMETER, AND THEIR PARAMETERS
CW RADAR, FMCW RADAR, FMCW ALTIMETER, AND THEIR PARAMETERSCW RADAR, FMCW RADAR, FMCW ALTIMETER, AND THEIR PARAMETERS
CW RADAR, FMCW RADAR, FMCW ALTIMETER, AND THEIR PARAMETERS
veerababupersonal22
 
在线办理(ANU毕业证书)澳洲国立大学毕业证录取通知书一模一样
在线办理(ANU毕业证书)澳洲国立大学毕业证录取通知书一模一样在线办理(ANU毕业证书)澳洲国立大学毕业证录取通知书一模一样
在线办理(ANU毕业证书)澳洲国立大学毕业证录取通知书一模一样
obonagu
 
14 Template Contractual Notice - EOT Application
14 Template Contractual Notice - EOT Application14 Template Contractual Notice - EOT Application
14 Template Contractual Notice - EOT Application
SyedAbiiAzazi1
 
Hybrid optimization of pumped hydro system and solar- Engr. Abdul-Azeez.pdf
Hybrid optimization of pumped hydro system and solar- Engr. Abdul-Azeez.pdfHybrid optimization of pumped hydro system and solar- Engr. Abdul-Azeez.pdf
Hybrid optimization of pumped hydro system and solar- Engr. Abdul-Azeez.pdf
fxintegritypublishin
 
AP LAB PPT.pdf ap lab ppt no title specific
AP LAB PPT.pdf ap lab ppt no title specificAP LAB PPT.pdf ap lab ppt no title specific
AP LAB PPT.pdf ap lab ppt no title specific
BrazilAccount1
 
Railway Signalling Principles Edition 3.pdf
Railway Signalling Principles Edition 3.pdfRailway Signalling Principles Edition 3.pdf
Railway Signalling Principles Edition 3.pdf
TeeVichai
 
Gen AI Study Jams _ For the GDSC Leads in India.pdf
Gen AI Study Jams _ For the GDSC Leads in India.pdfGen AI Study Jams _ For the GDSC Leads in India.pdf
Gen AI Study Jams _ For the GDSC Leads in India.pdf
gdsczhcet
 
Sachpazis:Terzaghi Bearing Capacity Estimation in simple terms with Calculati...
Sachpazis:Terzaghi Bearing Capacity Estimation in simple terms with Calculati...Sachpazis:Terzaghi Bearing Capacity Estimation in simple terms with Calculati...
Sachpazis:Terzaghi Bearing Capacity Estimation in simple terms with Calculati...
Dr.Costas Sachpazis
 
Immunizing Image Classifiers Against Localized Adversary Attacks
Immunizing Image Classifiers Against Localized Adversary AttacksImmunizing Image Classifiers Against Localized Adversary Attacks
Immunizing Image Classifiers Against Localized Adversary Attacks
gerogepatton
 
Design and Analysis of Algorithms-DP,Backtracking,Graphs,B&B
Design and Analysis of Algorithms-DP,Backtracking,Graphs,B&BDesign and Analysis of Algorithms-DP,Backtracking,Graphs,B&B
Design and Analysis of Algorithms-DP,Backtracking,Graphs,B&B
Sreedhar Chowdam
 
Final project report on grocery store management system..pdf
Final project report on grocery store management system..pdfFinal project report on grocery store management system..pdf
Final project report on grocery store management system..pdf
Kamal Acharya
 
NUMERICAL SIMULATIONS OF HEAT AND MASS TRANSFER IN CONDENSING HEAT EXCHANGERS...
NUMERICAL SIMULATIONS OF HEAT AND MASS TRANSFER IN CONDENSING HEAT EXCHANGERS...NUMERICAL SIMULATIONS OF HEAT AND MASS TRANSFER IN CONDENSING HEAT EXCHANGERS...
NUMERICAL SIMULATIONS OF HEAT AND MASS TRANSFER IN CONDENSING HEAT EXCHANGERS...
ssuser7dcef0
 

Recently uploaded (20)

MCQ Soil mechanics questions (Soil shear strength).pdf
MCQ Soil mechanics questions (Soil shear strength).pdfMCQ Soil mechanics questions (Soil shear strength).pdf
MCQ Soil mechanics questions (Soil shear strength).pdf
 
Nuclear Power Economics and Structuring 2024
Nuclear Power Economics and Structuring 2024Nuclear Power Economics and Structuring 2024
Nuclear Power Economics and Structuring 2024
 
CME397 Surface Engineering- Professional Elective
CME397 Surface Engineering- Professional ElectiveCME397 Surface Engineering- Professional Elective
CME397 Surface Engineering- Professional Elective
 
Fundamentals of Electric Drives and its applications.pptx
Fundamentals of Electric Drives and its applications.pptxFundamentals of Electric Drives and its applications.pptx
Fundamentals of Electric Drives and its applications.pptx
 
Unbalanced Three Phase Systems and circuits.pptx
Unbalanced Three Phase Systems and circuits.pptxUnbalanced Three Phase Systems and circuits.pptx
Unbalanced Three Phase Systems and circuits.pptx
 
Heap Sort (SS).ppt FOR ENGINEERING GRADUATES, BCA, MCA, MTECH, BSC STUDENTS
Heap Sort (SS).ppt FOR ENGINEERING GRADUATES, BCA, MCA, MTECH, BSC STUDENTSHeap Sort (SS).ppt FOR ENGINEERING GRADUATES, BCA, MCA, MTECH, BSC STUDENTS
Heap Sort (SS).ppt FOR ENGINEERING GRADUATES, BCA, MCA, MTECH, BSC STUDENTS
 
DESIGN A COTTON SEED SEPARATION MACHINE.docx
DESIGN A COTTON SEED SEPARATION MACHINE.docxDESIGN A COTTON SEED SEPARATION MACHINE.docx
DESIGN A COTTON SEED SEPARATION MACHINE.docx
 
Pile Foundation by Venkatesh Taduvai (Sub Geotechnical Engineering II)-conver...
Pile Foundation by Venkatesh Taduvai (Sub Geotechnical Engineering II)-conver...Pile Foundation by Venkatesh Taduvai (Sub Geotechnical Engineering II)-conver...
Pile Foundation by Venkatesh Taduvai (Sub Geotechnical Engineering II)-conver...
 
CW RADAR, FMCW RADAR, FMCW ALTIMETER, AND THEIR PARAMETERS
CW RADAR, FMCW RADAR, FMCW ALTIMETER, AND THEIR PARAMETERSCW RADAR, FMCW RADAR, FMCW ALTIMETER, AND THEIR PARAMETERS
CW RADAR, FMCW RADAR, FMCW ALTIMETER, AND THEIR PARAMETERS
 
在线办理(ANU毕业证书)澳洲国立大学毕业证录取通知书一模一样
在线办理(ANU毕业证书)澳洲国立大学毕业证录取通知书一模一样在线办理(ANU毕业证书)澳洲国立大学毕业证录取通知书一模一样
在线办理(ANU毕业证书)澳洲国立大学毕业证录取通知书一模一样
 
14 Template Contractual Notice - EOT Application
14 Template Contractual Notice - EOT Application14 Template Contractual Notice - EOT Application
14 Template Contractual Notice - EOT Application
 
Hybrid optimization of pumped hydro system and solar- Engr. Abdul-Azeez.pdf
Hybrid optimization of pumped hydro system and solar- Engr. Abdul-Azeez.pdfHybrid optimization of pumped hydro system and solar- Engr. Abdul-Azeez.pdf
Hybrid optimization of pumped hydro system and solar- Engr. Abdul-Azeez.pdf
 
AP LAB PPT.pdf ap lab ppt no title specific
AP LAB PPT.pdf ap lab ppt no title specificAP LAB PPT.pdf ap lab ppt no title specific
AP LAB PPT.pdf ap lab ppt no title specific
 
Railway Signalling Principles Edition 3.pdf
Railway Signalling Principles Edition 3.pdfRailway Signalling Principles Edition 3.pdf
Railway Signalling Principles Edition 3.pdf
 
Gen AI Study Jams _ For the GDSC Leads in India.pdf
Gen AI Study Jams _ For the GDSC Leads in India.pdfGen AI Study Jams _ For the GDSC Leads in India.pdf
Gen AI Study Jams _ For the GDSC Leads in India.pdf
 
Sachpazis:Terzaghi Bearing Capacity Estimation in simple terms with Calculati...
Sachpazis:Terzaghi Bearing Capacity Estimation in simple terms with Calculati...Sachpazis:Terzaghi Bearing Capacity Estimation in simple terms with Calculati...
Sachpazis:Terzaghi Bearing Capacity Estimation in simple terms with Calculati...
 
Immunizing Image Classifiers Against Localized Adversary Attacks
Immunizing Image Classifiers Against Localized Adversary AttacksImmunizing Image Classifiers Against Localized Adversary Attacks
Immunizing Image Classifiers Against Localized Adversary Attacks
 
Design and Analysis of Algorithms-DP,Backtracking,Graphs,B&B
Design and Analysis of Algorithms-DP,Backtracking,Graphs,B&BDesign and Analysis of Algorithms-DP,Backtracking,Graphs,B&B
Design and Analysis of Algorithms-DP,Backtracking,Graphs,B&B
 
Final project report on grocery store management system..pdf
Final project report on grocery store management system..pdfFinal project report on grocery store management system..pdf
Final project report on grocery store management system..pdf
 
NUMERICAL SIMULATIONS OF HEAT AND MASS TRANSFER IN CONDENSING HEAT EXCHANGERS...
NUMERICAL SIMULATIONS OF HEAT AND MASS TRANSFER IN CONDENSING HEAT EXCHANGERS...NUMERICAL SIMULATIONS OF HEAT AND MASS TRANSFER IN CONDENSING HEAT EXCHANGERS...
NUMERICAL SIMULATIONS OF HEAT AND MASS TRANSFER IN CONDENSING HEAT EXCHANGERS...
 

Kotlin Data Model

  • 1. Kotlin Data Model 黃千碩 (Kros) oSolve, Ltd./打⼯工趣 Mobile App Developer
  • 2. Outline • Android data model 演化史 • Kotlin 介紹 • Kotlin classes/data classes 介紹 • Kotlin companion object 介紹 • Unit testing • What’s next?
  • 3. Data Model 演化史 • 當第⼀一次在 Android 上寫 data model 時
  • 4. Data Model 演化史 • 定義 property
  • 5. public class User {
 private String name;
 private String email; 
 private int age;
 
 private Date createdAt;
 }
  • 6. Data Model 演化史 • 定義 property • ⼿手動實作 get, set
  • 7. Data Model 演化史 • 定義 property • ⼿手動實作 get, set
  • 8. Data Model 演化史 • 定義 property • ⼿手動實作 get, set • IDE 可以幫忙產⽣生 setter, getter
  • 9. Data Model 演化史 • 定義 property • ⼿手動實作 get, set • IDE 可以幫忙產⽣生 setter, getter, equal, hash, toString
  • 10. public class User implements Parcelable {
 private String name;
 
 private String email;
 
 private int age;
 
 private Date createdAt;
 
 @Override
 public int hashCode() {
 int result = name != null ? name.hashCode() : 0;
 result = 31 * result + (email != null ? email.hashCode() : 0);
 result = 31 * result + age;
 result = 31 * result + (createdAt != null ? createdAt.hashCode() : 0);
 return result;
 }
 
 @Override
 public boolean equals(Object o) {
 if (this == o) return true;
 if (o == null || getClass() != o.getClass()) return false;
 
 User user = (User) o;
 
 if (age != user.age) return false;
 if (name != null ? !name.equals(user.name) : user.name != null) return false;
 if (email != null ? !email.equals(user.email) : user.email != null) return false;
 return createdAt != null ? createdAt.equals(user.createdAt) : user.createdAt == null;
 
 }
 
 @Override
 public String toString() {
 return "User{" +
 "name='" + name + ''' +
 ", email='" + email + ''' +
 ", age=" + age +
 ", createdAt=" + createdAt +
 '}';
 }
 
 public String getName() {
 return name;
 }
 
 public void setName(String name) {
 this.name = name;
 }
 
 public String getEmail() {
 return email;
 }
 
 public void setEmail(String email) {
 this.email = email;
 }
 
 public int getAge() {
 return age;
 }
 
 public void setAge(int age) {
 this.age = age;
 }
 
 public Date getCreatedAt() {
 return createdAt;
 }
 
 public void setCreatedAt(Date createdAt) {
 this.createdAt = createdAt;
 }
  • 14. Parcelable • 遇到 parcelable • ⼿手動實作 • ⽤用 android studio plugin 產⽣生 parcelable 實作
  • 15. public class User implements Parcelable {
 private String name;
 
 private String email;
 
 private int age;
 
 private Date createdAt;
 
 @Override
 public int hashCode() {
 int result = name != null ? name.hashCode() : 0;
 result = 31 * result + (email != null ? email.hashCode() : 0);
 result = 31 * result + age;
 result = 31 * result + (createdAt != null ? createdAt.hashCode() : 0);
 return result;
 }
 
 @Override
 public boolean equals(Object o) {
 if (this == o) return true;
 if (o == null || getClass() != o.getClass()) return false;
 
 User user = (User) o;
 
 if (age != user.age) return false;
 if (name != null ? !name.equals(user.name) : user.name != null) return false;
 if (email != null ? !email.equals(user.email) : user.email != null) return false;
 return createdAt != null ? createdAt.equals(user.createdAt) : user.createdAt == null;
 
 }
 
 @Override
 public String toString() {
 return "User{" +
 "name='" + name + ''' +
 ", email='" + email + ''' +
 ", age=" + age +
 ", createdAt=" + createdAt +
 '}';
 }
 
 public String getName() {
 return name;
 }
 
 public void setName(String name) {
 this.name = name;
 }
 
 public String getEmail() {
 return email;
 }
 
 public void setEmail(String email) {
 this.email = email;
 }
 
 public int getAge() {
 return age;
 }
 
 public void setAge(int age) {
 this.age = age;
 }
 
 public Date getCreatedAt() {
 return createdAt;
 }
 
 public void setCreatedAt(Date createdAt) {
 this.createdAt = createdAt;
 }
 
 @Override
 public int describeContents() { return 0; }
 
 @Override
 public void writeToParcel(Parcel dest, int flags) {
 dest.writeString(this.name);
 dest.writeString(this.email);
 dest.writeInt(this.age);
 dest.writeLong(this.createdAt != null ? this.createdAt.getTime() : -1);
 }
 
 public User() {}
 
 protected User(Parcel in) {
 this.name = in.readString();
 this.email = in.readString();
 this.age = in.readInt();
 long tmpCreatedAt = in.readLong();
 this.createdAt = tmpCreatedAt == -1 ? null : new Date(tmpCreatedAt);
 }
 
 public static final Creator<User> CREATOR = new Creator<User>() {
 @Override
 public User createFromParcel(Parcel source) {return new User(source);}
 
 @Override
 public User[] newArray(int size) {return new User[size];}
 };

  • 16. public class User implements Parcelable {
 private String name;
 
 private String email;
 
 private int age;
 
 private Date createdAt;
 
 @Override
 public int hashCode() {
 int result = name != null ? name.hashCode() : 0;
 result = 31 * result + (email != null ? email.hashCode() : 0);
 result = 31 * result + age;
 result = 31 * result + (createdAt != null ? createdAt.hashCode() : 0);
 return result;
 }
 
 @Override
 public boolean equals(Object o) {
 if (this == o) return true;
 if (o == null || getClass() != o.getClass()) return false;
 
 User user = (User) o;
 
 if (age != user.age) return false;
 if (name != null ? !name.equals(user.name) : user.name != null) return false;
 if (email != null ? !email.equals(user.email) : user.email != null) return false;
 return createdAt != null ? createdAt.equals(user.createdAt) : user.createdAt == null;
 
 }
 
 @Override
 public String toString() {
 return "User{" +
 "name='" + name + ''' +
 ", email='" + email + ''' +
 ", age=" + age +
 ", createdAt=" + createdAt +
 '}';
 }
 
 public String getName() {
 return name;
 }
 
 public void setName(String name) {
 this.name = name;
 }
 
 public String getEmail() {
 return email;
 }
 
 public void setEmail(String email) {
 this.email = email;
 }
 
 public int getAge() {
 return age;
 }
 
 public void setAge(int age) {
 this.age = age;
 }
 
 public Date getCreatedAt() {
 return createdAt;
 }
 
 public void setCreatedAt(Date createdAt) {
 this.createdAt = createdAt;
 }
 
 @Override
 public int describeContents() { return 0; }
 
 @Override
 public void writeToParcel(Parcel dest, int flags) {
 dest.writeString(this.name);
 dest.writeString(this.email);
 dest.writeInt(this.age);
 dest.writeLong(this.createdAt != null ? this.createdAt.getTime() : -1);
 }
 
 public User() {}
 
 protected User(Parcel in) {
 this.name = in.readString();
 this.email = in.readString();
 this.age = in.readInt();
 long tmpCreatedAt = in.readLong();
 this.createdAt = tmpCreatedAt == -1 ? null : new Date(tmpCreatedAt);
 }
 
 public static final Creator<User> CREATOR = new Creator<User>() {
 @Override
 public User createFromParcel(Parcel source) {return new User(source);}
 
 @Override
 public User[] newArray(int size) {return new User[size];}
 };
 隨隨便便便便就超過 100 ⾏行行
  • 17. Parcelable • 遇到 parcelable • ⼿手動實作 • ⽤用 plugin 產⽣生 Parcelable 實作 • 當 class 越來來越多,property 越來來越多,開發的⼈人越來來越多 • 每次實作就成了了問題
  • 19. Libraries • Google AutoValue
 https://github.com/google/auto • Lombok
 https://github.com/rzwitserloot/lombok

  • 20. AutoValue • 只要定義好 interface,就會⾃自動產⽣生 model • ⾃自動產⽣生 setter, getter, equal, hash, toString • 有 plugin ⾃自動產⽣生 parcelable 實作 • Builder pattern
  • 21. @AutoValue
 public abstract class User implements Parcelable {
 
 public abstract String name();
 
 @Nullable
 public abstract String email();
 
 public abstract int age();
 
 public abstract Date createdAt();
 
 public static User create(String name, String email, int age, Date createdAt) {
 return builder()
 .name(name)
 .email(email)
 .age(age)
 .createdAt(createdAt)
 .build();
 }
 
 public static Builder builder() {return new AutoValue_User.Builder();}
 
 @AutoValue.Builder
 public abstract static class Builder {
 
 public abstract Builder name(String name);
 
 public abstract Builder email(String email);
 
 public abstract Builder age(int age);
 
 public abstract Builder createdAt(Date createdAt);
 
 public abstract User build();
 }
 }
  • 22. AutoValue • 除此之外,加入兩兩個概念念: • Immutable Object: 預設產⽣生的 object 都是 value object,沒有 setter,只有 getter • Null-safety: 每個 property 都需定義 NonNull, Nullable
  • 23. @AutoValue
 public abstract class User implements Parcelable {
 
 public abstract String name();
 
 @Nullable
 public abstract String email();
 
 public abstract int age();
 
 public abstract Date createdAt();
 
 public static User create(String name, String email, int age, Date createdAt) {
 return builder()
 .name(name)
 .email(email)
 .age(age)
 .createdAt(createdAt)
 .build();
 }
 
 public static Builder builder() {return new AutoValue_User.Builder();}
 
 @AutoValue.Builder
 public abstract static class Builder {
 
 public abstract Builder name(String name);
 
 public abstract Builder email(String email);
 
 public abstract Builder age(int age);
 
 public abstract Builder createdAt(Date createdAt);
 
 public abstract User build();
 }
 }
  • 24. Kotlin 介紹 val name: String = "Android"
  • 25. Kotlin 介紹 val name: String = "Android" val email: String? = null
  • 26. Kotlin 介紹 val name: String = "Android" val email: String? = null var name: String = "Android"
  • 27. Kotlin 介紹 val name: String = "Android" val email: String? = null var name: String = "Android"
 name = "Android Taipei"
  • 28. Kotlin 介紹 val name: String = "Android" val email: String? = null var name: String = "Android"
 name = "Android Taipei" • val: Assign-once (read-only) local variable • var: Mutable variable:
  • 29. Kotlin 介紹 fun doSomething(name: String) : String { return name.toUpperCase() }
  • 32. class User constructor(
 name: String, email: String?,
 age: Int,
 createdAt: Date
 ) { } • 定義 constructor
  • 33. class User(
 name: String, email: String?,
 age: Int,
 createdAt: Date
 ) { } • 可以省略略關鍵字
  • 34. class User(
 name: String, email: String?,
 age: Int,
 createdAt: Date
 ) { var name: String = name, var email: String? = email,
 var age: Int = age,
 var createdAt: Date = createdAt } • 定義 properties
  • 35. class User(
 var name: String, var email: String?,
 var age: Int,
 var createdAt: Date
 ) { } • 更更簡單的寫法
  • 36. class User(
 val name: String, val email: String?,
 val age: Int,
 val createdAt: Date
 ) { } • 定義 immutable properties
  • 37. class User(
 val name: String = "No Name", val email: String? = null,
 val age: Int = 0,
 val createdAt: Date = Date()
 ) { } • 給預設值
  • 38. Data Classes • The compiler automatically derives the following members from all properties declared in the primary constructor: • 根據你定義的 properties,⾃自動幫你產⽣生以下四種內容 • equals()/hashCode() • toString() • componentN() functions • copy()
  • 39. Data Classes • Primary constructor ⾄至少要有⼀一個參參數 • 參參數只能是 val, var
  • 40. class User (
 val name: String, val email: String?,
 val age: Int,
 val createdAt: Date
 ) { }
  • 41. data class User(
 val name: String, val email: String?,
 val age: Int,
 val createdAt: Date
 ) { }
  • 42. Parcelable • 當然也有開發者提供 parcelable 的 plugin,⾃自動產⽣生 parcelable 實作
  • 43. data class User(
 val name: String, val email: String?,
 val age: Int,
 val createdAt: Date
 ) { }
  • 44. data class User(
 val name: String, val email: String?,
 val age: Int,
 val createdAt: Date
 ) : AutoParcelable { }
  • 46. data class User(
 val name: String, val email: String?,
 val age: Int,
 val createdAt: Date
 ) : AutoParcelable { } public class User implements Parcelable {
 private String name;
 
 private String email;
 
 private int age;
 
 private Date createdAt;
 
 @Override
 public int hashCode() {
 int result = name != null ? name.hashCode() : 0;
 result = 31 * result + (email != null ? email.hashCode() : 0);
 result = 31 * result + age;
 result = 31 * result + (createdAt != null ? createdAt.hashCode() : 0);
 return result;
 }
 
 @Override
 public boolean equals(Object o) {
 if (this == o) return true;
 if (o == null || getClass() != o.getClass()) return false;
 
 User user = (User) o;
 
 if (age != user.age) return false;
 if (name != null ? !name.equals(user.name) : user.name != null) return false;
 if (email != null ? !email.equals(user.email) : user.email != null) return false;
 return createdAt != null ? createdAt.equals(user.createdAt) : user.createdAt == null;
 
 }
 
 @Override
 public String toString() {
 return "User{" +
 "name='" + name + ''' +
 ", email='" + email + ''' +
 ", age=" + age +
 ", createdAt=" + createdAt +
 '}';
 }
 
 public String getName() {
 return name;
 }
 
 public void setName(String name) {
 this.name = name;
 }
 
 public String getEmail() {
 return email;
 }
 
 public void setEmail(String email) {
 this.email = email;
 }
 
 public int getAge() {
 return age;
 }
 
 public void setAge(int age) {
 this.age = age;
 }
 
 public Date getCreatedAt() {
 return createdAt;
 }
 
 public void setCreatedAt(Date createdAt) {
 this.createdAt = createdAt;
 }
 
 @Override
 public int describeContents() { return 0; }
 
 @Override
 public void writeToParcel(Parcel dest, int flags) {
 dest.writeString(this.name);
 dest.writeString(this.email);
 dest.writeInt(this.age);
 dest.writeLong(this.createdAt != null ? this.createdAt.getTime() : -1);
 }
 
 public User() {}
 
 protected User(Parcel in) {
 this.name = in.readString();
 this.email = in.readString();
 this.age = in.readInt();
 long tmpCreatedAt = in.readLong();
 this.createdAt = tmpCreatedAt == -1 ? null : new Date(tmpCreatedAt);
 }
 
 public static final Creator<User> CREATOR = new Creator<User>() {
 @Override
 public User createFromParcel(Parcel source) {return new User(source);}
 
 @Override
 public User[] newArray(int size) {return new User[size];}
 };
 @AutoValue
 public abstract class User implements Parcelable {
 
 public abstract String name();
 
 @Nullable
 public abstract String email();
 
 public abstract int age();
 
 public abstract Date createdAt();
 
 public static User create(String name, String email, int age, Date createdAt) {
 return builder()
 .name(name)
 .email(email)
 .age(age)
 .createdAt(createdAt)
 .build();
 }
 
 public static Builder builder() {return new AutoValue_User.Builder();}
 
 @AutoValue.Builder
 public abstract static class Builder {
 
 public abstract Builder name(String name);
 
 public abstract Builder email(String email);
 
 public abstract Builder age(int age);
 
 public abstract Builder createdAt(Date createdAt);
 
 public abstract User build();
 }
 }
  • 47. Copy • 很多時候我們會更更新 object 內容 • 如何更更新⼀一個 immutable object? • 利利⽤用 copy()
  • 48. class User(
 val name: String, val email: String?
 ) { }
  • 49. class User(
 val name: String, val email: String?
 ) { fun copy(name: String = this.name, email: String? = this.email): User {
 return User(name = name, email = email)
 } } • copy() 的實作如下
  • 50. data class User(
 val name: String, val email: String?,
 val age: Int,
 val createdAt: Date
 ) : AutoParcelable { }
  • 51. data class User(
 val name: String,
 val email: String?,
 val age: Int,
 val createdAt: Date
 ) : AutoParcelable {
 fun updateAge(newAge: Int): User {
 return copy(age = newAge)
 }
 }
  • 52. data class User(
 val name: String,
 val email: String?,
 val age: Int,
 val createdAt: Date
 ) : AutoParcelable {
 fun updateAge(newAge: Int): User {
 return copy(age = newAge)
 }
 }
  • 53. data class User(
 val name: String,
 val email: String?,
 val age: Int,
 val createdAt: Date
 ) : AutoParcelable {
 fun updateAge(newAge: Int): User {
 return copy(age = newAge)
 }
 } user = user.updateAge(18);
 assertThat(user.getAge()).isEqualTo(18);
  • 54. Companion Object • Kotlin 中沒有 static 的概念念,改⽤用 Companion Object
  • 55. Companion Object • Kotlin 中沒有 static 的概念念,改⽤用 Companion Object • Static method -> Companion method
  • 56. class User(
 val name: String, val email: String?
 ) { }
  • 57. class User(
 val name: String, val email: String?
 ) { companion object {
 fun myCompanionMethod() {
 // ...
 }
 } }
  • 58. class User(
 val name: String, val email: String?
 ) { companion object {
 fun myCompanionMethod() {
 // ...
 }
 } } // Java 中使⽤用 User.Companion.myCompanionMethod();
  • 59. Companion Object • Kotlin 中沒有 static 的概念念,改⽤用 Companion Object • Static method -> companion method • 舉例例:ViewModel (MVVM 中的 ViewModel)
  • 60. User user = ... // age = 50 UserViewModel viewModel = createViewModel(user) viewModel.getAgeString(); // "50 歲"
  • 62. class UserViewModel(
 context: Context,
 val user: User
 ) {
 val ageString: String
 }
  • 63. class UserViewModel(
 context: Context,
 val user: User
 ) {
 val ageString: String
 
 init {
 ageString = context.getString(R.string.age_is, user.age.toString())
 }
 }
  • 64. class UserViewModel(
 context: Context,
 val user: User
 ) {
 val ageString: String
 
 init {
 ageString = context.getString(R.string.age_is, user.age.toString())
 }
 } UserViewModel viewModel = new UserViewModel(context, user); viewModel.getAgeString(); // “50 歲"
  • 65. Companion Object • 想要使⽤用 data classes • 使⽤用 companion method
  • 66. data class UserViewModel(
 val user: User,
 val ageString: String
 ) { 
 }
  • 67. data class UserViewModel(
 val user: User,
 val ageString: String
 ) {
 companion object {
 fun create(context: Context, user: User): UserViewModel {
 val ageString = context.getString(R.string.age_is, user.age.toString())
 return UserViewModel(user, ageString)
 }
 }
 }
  • 68. data class UserViewModel(
 val user: User,
 val ageString: String
 ) {
 companion object {
 fun create(context: Context, user: User): UserViewModel {
 val ageString = context.getString(R.string.age_is, user.age.toString())
 return UserViewModel(user, ageString)
 }
 }
 }
  • 69. Private Constructor • 與 Java 相同,可以 private constructor,讓維護更更容易易
  • 70. data class UserViewModel(
 val user: User,
 val ageString: String
 ) {
 companion object {
 fun create(context: Context, user: User): UserViewModel {
 val ageString = context.getString(R.string.age_is, user.age.toString())
 return UserViewModel(user, ageString)
 }
 }
 }
  • 71. data class UserViewModel private constructor(
 val user: User,
 val ageString: String
 ) {
 companion object {
 fun create(context: Context, user: User): UserViewModel {
 val ageString = context.getString(R.string.age_is, user.age.toString())
 return UserViewModel(user, ageString)
 }
 }
 }
  • 72. data class UserViewModel private constructor(
 val user: User,
 val ageString: String
 ) {
 companion object {
 fun create(context: Context, user: User): UserViewModel {
 val ageString = context.getString(R.string.age_is, user.age.toString())
 return UserViewModel(user, ageString)
 }
 }
 } // Java 中使⽤用 new UserViewModel();
  • 73. data class UserViewModel private constructor(
 val user: User,
 val ageString: String
 ) {
 companion object {
 fun create(context: Context, user: User): UserViewModel {
 val ageString = context.getString(R.string.age_is, user.age.toString())
 return UserViewModel(user, ageString)
 }
 }
 } // Java 中使⽤用 new UserViewModel();
  • 74. data class UserViewModel private constructor(
 val user: User,
 val ageString: String
 ) {
 companion object {
 fun create(context: Context, user: User): UserViewModel {
 val ageString = context.getString(R.string.age_is, user.age.toString())
 return UserViewModel(user, ageString)
 }
 }
 } // Java 中使⽤用 new UserViewModel(); UserViewModel viewModel = UserViewModel.Companion.create(context, user);
  • 75. data class UserViewModel private constructor(
 val user: User,
 val ageString: String
 ) {
 companion object {
 fun create(context: Context, user: User): UserViewModel {
 val ageString = context.getString(R.string.age_is, user.age.toString())
 return UserViewModel(user, ageString)
 }
 }
 } // Java 中使⽤用 new UserViewModel(); UserViewModel viewModel = UserViewModel.Companion.create(context, user); viewModel.getAgeString(); // "50 歲"
  • 76. Unit Test • Kotlin 所有的東⻄西,預設都是 final
  • 77. Unit Test • Kotlin 所有的東⻄西,預設都是 final • 當要 Mock (2.0) 時,會出現以下問題: org.mockito.exceptions.base.MockitoException: 
 Cannot mock/spy class com.example.kotlindataclass.model.xxx cannot mock/spy because :
 - final class
  • 78. Solution • 啟動 Mockito 2 的 option 功能 
 (opt-in mocking of final classes/methods) • 在路路徑 test/resources/mockito-extensions 底下新增檔案:
 org.mockito.plugins.MockMaker • 檔案內容:
 mock-maker-inline
  • 80. 如何開始導入 Kotlin 1.挑選最少⽤用到的 Data Model 2.對此 Data Model 寫測試 (encode/decode) 3.透過 Android Studio Converter (command+shift+a) 4.在⼀一個 commit 裡⼀一次做完 (要反悔悔也容易易)
  • 81. What’s Next • ViewModel 採⽤用 Kotlin • Presenter 採⽤用 Kotlin • Helper 採⽤用 Kotlin • View 採⽤用 Kotlin • …
  • 82. What’s Next • 資料操作 • Collections: List, Set, Map • map, filter, find…etc. • more…
  • 83. Using Kotlin for Android today!
  • 84. Reference • Kotlin Data Classes
 https://kotlinlang.org/docs/reference/data-classes.html • Kotlin 的 data class 會對你的程式產⽣生什什麼樣的化學反應
 https://ingramchen.io/blog/2017/06/kotlin-data-class.html • Kotlin Koans
 https://kotlinlang.org/docs/tutorials/koans.html • Mock the unmockable
 https://github.com/mockito/mockito/wiki/What%27s-new-in- Mockito-2#mock-the-unmockable-opt-in-mocking-of-final-classesmethods