Weitere ähnliche Inhalte Ähnlich wie Kotlinアンチパターン (20) Mehr von Recruit Lifestyle Co., Ltd. (20) Kotlinアンチパターン2. 自己紹介
● Naoto Nakazato
○ Android開発歴 7年くらい
● Recruit Lifestyle
○ 2017年6月〜
○ HOT PEPPER Beauty
● アカウント
○ Twitter: @oxsoft
○ Facebook: naoto.nakazato
○ GitHub: oxsoft
○ Qiita: oxsoft
27. アンチパターン
apply内でプロパティアクセス形式の処理を書く
val button = Button(context)
button.text = "hello" // JavaのsetText(...)が呼ばれる
// ... buttonの設定が続く ...
val button = Button(context).apply {
text = "hello"
// ... buttonの設定が続く ...
}
↓ apply を使って処理をまとめよう!
31. 解決策の例3
apply 禁止( also を使う)
我々のチームでは、let と also のみに限定
val button = Button(context).also {
it.text = "hello"
}
33. Nullable と NonNull
Nullable / NonNull はKotlinの大きな魅力の1つ
言語機能の説明
val nullable: String? = null // OK
val nonNull: String = null // NG
nullable.length // NG
nullable!!.length // OK
nullable?.length // OK
nonNull.length // OK
40. data classとは
● equals/hashCodeやtoStringをよしなにoverride
● componentNやcopyなどのメソッドを生成
言語機能の説明
data class User(val name: String, val age: Int)
val alice = User("Alice", 27)
alice == User("Alice", 27) // true
alice.toString() // "User(name=Alice, age=27)"
val (name, age) = alice
val nextYear = alice.copy(age = 28)
52. 状態を持ちつつも、一部の処理は子クラスで実装させたい場合
interface IState {
var state: String
}
interface DefaultImpl : IState {
fun abstract(): String
fun default() { ... }
}
class State : IState {
override var state: String = ""
}
class UserModel : DefaultImpl, IState by State() {
override fun abstract(): String {
return "concrete"
}
}
IState
State
DefaultImpl
UserModel
状態をインタフェースとして切り出し、
状態を実装したクラスを用意する
62. 通常の代入とcustom getter
● 通常の代入は、インスタンス生成時に計算される
● lazyは、最初にアクセスがあった時に計算される
● custom getterは、アクセスがあるたびに計算される
言語機能の説明
val isAdmin = userId == ADMIN_ID
val isAdmin by lazy { userId == ADMIN_ID }
val isAdmin get() = userId == ADMIN_ID
67. delegated propertyの使用例
ついでに紹介
class Extra<out T> : ReadOnlyProperty<Activity, T> {
override fun getValue(
thisRef: Activity,
property: KProperty<*>
): T = thisRef.intent.extras.get(property.name) as T
}
fun Intent.put(
prop: KProperty1<*, String>, value: String
): Intent = this.putExtra(prop.name, value)
68. delegated propertyの使用例
ついでに紹介
class ProfileActivity : AppCompatActivity() {
val userId: String by Extra()
companion object {
fun createIntent(context: Context, userId: String): Intent {
return Intent(context, ProfileActivity::class.java)
.put(ProfileActivity::userId, userId)
}
}
}
かなりの部分を隠蔽することができる
参考:https://speakerdeck.com/sakuna63/kotlins-delegated-properties-x-android
73. 解決策の例
lateinit を使い、onCreateView で代入する
Data Bindingの場合も、binding自体はlateinitが良い
lateinit var button: Button
override fun onCreateView(...): View? {
val view = ...
button = view.findViewById(R.id.button)
return view
}
77. アンチパターン2
計算量が多い
private val total: Int
get() = countView(root)
fun countView(view: View): Int = if (view is ViewGroup) {
(0 until view.childCount).map {
countView(view.getChildAt(it))
}.sum()
} else {
1
}
84. 変数の委譲
もちろん以下のように書くこともできるが、やや冗長
private val owner = Person()
var ownerName: String by object : ReadWriteProperty<Any, String> {
override fun getValue(thisRef: Any, property: KProperty<*>): String = owner.name
override fun setValue(thisRef: Any, property: KProperty<*>, value: String) {
owner.name = value
}
}
言語機能の説明