[kotlin] class, object, interface -1
22450 ワード
kotlin in action을 보고 정리한 글입니다
ああ、勉強したくない。
コトリンのclass、interfaceはjavaといくつかの違いがあります.
たとえば、インタフェースには属性宣言があります.
つまりfinalとpublicはdefaultです.
Cottlinに新しく登場したdataclassにはdefaultメソッドがあり、既存のクラスメソッドを一つ一つ定義する手間を避けることができます.
Defining class hierarchies
重要な概念
Interfaces in kotlin
インタフェースにはabstractメソッド、non-astractメソッドを含めることができますが、ステータスを含めることはできません.
interface Clickable {
fun click()
}
上記のコードはabstract method clickを定義しています.英語での声明や実施で混乱する可能性があると思います.もし私たちがそれを指摘したら、
上記のように、インタフェースの作成は宣言され、インタフェースを使用してclassを作成することを実装と呼びます.
잘 구분하자
class Button: Clickable {
override fun click() = println("I was clicked")
}
>>> Button().click()
// I was clicked
Javaまたはjavascriptとは異なり、Cottlinはextends(インタフェースのタイプスクリプト)の代わりに:
を使用し、構文を簡略化します.classは複数のインタフェースを実現することができ、extendsは最大1つのclassに対してjavaと同じである可能性がある.
overrideはjavaの@Overrideコメントで、javaとは異なりkotlinはoverride修飾子を使用する必要があります.コットリンはこのような断言を採用し、Javaで発生する可能性のある意外なカバーを防止した.
インタフェースメソッドはdefaultで実装できます.Java 8は
default
keywordを使用する必要がありますが、Cortlinではこのような注釈はありません.interface Clickable {
fun click()
fun showOff() = println("I'm clickable!")
}
ここでclick法をRegular method declaration
と呼ぶ.showOffメソッドは
method with a default implementation
と呼ばれています.Clickableインタフェースを実装する場合、デフォルト実装のshowOffを使用する以外は、Clickに対して必要な実装を実行するだけでよい.もちろん、showOffでもカバーできます
interface Focusable {
fun setFocus(b: Boolean) = println("I ${if (b) "god" else "lost"}focus.")
fun showOff() = println("I'm focusable!")
}
Buttonクラスでは、defaultインプリメンテーションが適用された2つのクラスと、適用されていない2つのクラスを同じメソッドで実装するとどうなりますか?この場合、明確に書き換えるべきです.次のエラーが表示されます.The class 'Button' must
override public open fun showOff() because it inherits
many implementations of it.
class Button: Clickable, Focusable {
override fun click() = println("I was clicked")
override fun showOff() {
super<Clickable>.showOff()
super<Focusable>.showOff()
}
}
ここでshowOffメソッドは2つのインタフェースで同じなので、明示的に上書きする必要があります.インタフェースに適用されるdefault実装を継承するために、super
キーワードが使用される.Javaと文法の違いを見てみましょう// java
Clickable.super.showOff()
// kotlin
super<Clickable>.showOff()
open, final, and abstract modifiers: final by default
Javaでは、superclass付きfinalキーワードのメソッドはsubclassで上書きできません.ベースクラスのインプリメンテーションを変更すると、サブクラスは、これらのベースクラスが脆弱であると誤ってベースクラスのインプリメンテーションを推定します.superclassが書き換え可能な実装を詳細に説明していない場合、baseclassへの小さな変更は複数のコードで副作用を引き起こす可能性があります.
design and document for inheritance or else prohibit it
; Joshua Bloch-Effective Javaの作者
Javaでこれらの副作用を最小限に抑えるためには、subclassに上書きされたくない方法はfinal modifierを使用して強制しなければならない.
kotlinはfinal modifierをdefaultとして使用し,このsie効果を最小化した.
上書きを可能にするためにはopen修飾子を明確に使用する必要があります.
open class RichButton: Clickable {
fun disable() {}
open fun animate() {}
override fun click() {}
}
disableに加えて、animate、clickは他の関数で上書きできます.上書きする関数が他のインプリメンテーションでfinalである場合は、明確に指定する必要があります.
open class RichButton: Clickable {
final override fun click() {}
}
Javaと同様に、コトリンではabstract classで宣言されたabstract関数は常に他のclassで実装される必要があるため、open修飾子を追加する必要はありません.abstract class Animated {
abstract fun animate()
open fun stopAnimating() {}
fun animateTwice() {}
}
ここでanimateはopen修飾子を追加する必要はありませんが、animateTwiceはoverrideのターゲットではありません.Visibility modifiers: public by default
classのpropertiesの制御権を詳細に説明できる修飾子を可視修飾子と呼び、パッケージに使用します.
コトリンのdefault visibility modifierはpublicです.
コトリンにはinternalというvisibility modifierがあり、モジュール内部からしかアクセスできません.
internal open class TalkativeButton: Focusable {
private fun yell() = println("Hey!")
protected fun whisper() = println("Let's talk!")
}
fun TalkativeButton.giveSpeech() {
yell()
whisper()
}
TalkativeButton.giveSpeechは公開されており、TalkativeButtonは内部声明である.less-bisibleタイプへの参照は禁止されているため、内部クラスTalkativeButtonをreferenceタイプとして使用して共通の拡張関数を作成することはできません.'public' member exposes its 'internal' receiver type TalkativeButton
この問題を解決するには、giveSpeechを内部に設定するか、classを共通に設定する必要があります.Javaでは、同じパッケージ内から保護されたメンバーにアクセスできますが、コトリンでは不可能です.保護されたメンバーは、クラス内またはサブクラスにのみアクセスできます.
Inner and nested classes: nested by default
Javaのように、コトリンでもclass内部でclassを宣言することができます.違いは、cottinのnested classがoutherclassインスタンスにデフォルトでアクセスできないことです.
interface State: Serializable
interface View {
fun getCurrentState(): State
fun restoreState(state: State) {}
JavaスタイルでViewを実現するButton classを実現しましょうpublic class Button implements View {
@Override
public State getCurrentState() {
return new ButtonState();
}
@Override
public void restoreState(State state) { /*...*/}
public class ButtonState implements State { /*...*/ }
}
Stateインタフェースを用いてButtonクラス内部でButtonに関連する状態Button Stateを実現した.getCurrentStateを使用してステータスインスタンスを戻そうとしますが、java.io.NotSerializable- Exception: Button
エラーが発生する可能性があります.Javaでは、classの内部で別のclassを定義するとdefaultが内部classになるため、ButtonState classがButton classを参照し、類似のエラーが発生します.コトリンではどうなるの?
class Button: View {
override fun getCurrentState(): State = ButtonState()
override fun restoreState(state: State) {/*...*/}
class ButtonState : State {/*...*/}
}
Cottlinでは、nested classはjavaのstatic nested classと同じです.Inner classのように動作するには、inner修飾子を明示的に追加する必要があります.Kotlin action p.76のFigure 4.1
Nested classはouterclassの参照を持たず、inner classはouterclassの参照を持つ.
cottlinにouterclassのreferenceを取得させるには、次の手順に従います.
class Outer {
inner class Inner {
fun getOuterReference(): Outer = this@Outer
}
}
Sealed classes: defining restricted class hierarchies
interface Expr
class Num(val value: Int) : Expr
class Sum(val left: Expr, val right: Expr) : Expr
fun eval(e: Expr): Int =
when (e) {
is Num -> e.value
is Sum -> eval(e.right) + eval(e.left)
else ->
throw IllegalArgumentException("Unknown expression")
}
when文を使用する場合、defaultオプションelseを同時に作成するのは不便です.また、subclassの作成時にfun evalを変更しないと、予期せぬエラーが発生する可能性があります.cottlinでは、superclassにsealed modifierを付けることで、コンパイラにsubclassを生成できないことを伝えることができます.
sealed class Expr {
class Num(val value: Int) : Expr()
class Sum(val left: Expr, val right: Expr) : Expr()
}
すべてのシールクラスのsubclassをwhen文内で処理する場合は、default branchを作成する必要はありません.ちなみにsealed modifierにはopenが含まれているのでopen modifierを追加する必要はありません.sealedインタフェースはありません.内部では、Expr classはプライベートコンストラクション関数で構成され、class内部でのみ使用できます.
Reference
この問題について([kotlin] class, object, interface -1), 我々は、より多くの情報をここで見つけました https://velog.io/@jay/kotlin-class-object-interface-1テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol