Kotlin特集「十」:インタフェースと関数インタフェース(Functional(SAM)interfaces)
22218 ワード
前言:両親があなたを必要とする時、涙を除いて、何もありません;子供があなたを必要としないでください.耻ずかしい以外に何もありません.自分が過去を振り返る時、無駄にする以外に何もない.
一、概説
Kotlinのインタフェースは、抽象的なメソッドの宣言を含んでもよいし、メソッド実装を含んでもよい.インタフェースと抽象クラスの違いは、インタフェースがステータスを格納できないことです.これらは属性を持つことができますが、これらの属性は抽象的であるか、アクセサ実装を提供する必要があります.同時にKotlin 1.4バージョンからインタフェースのSAM変換をサポートしています.
KotlinのインタフェースはJava 8と同様で、
インタフェースでインプリメンテーションが提供されていない方法のデフォルトは
二、インタフェースの使用
2.1実装インタフェース
1つのクラスまたはオブジェクトは、1つまたは複数のインタフェースを実装することができる.KotlinではJavaのように
印刷データは次のとおりです.
2.2インタフェースのプロパティ
インタフェースでプロパティを宣言したり、インタフェースで宣言したプロパティを抽象的にしたり、アクセサに実装したりすることができます.インタフェースで宣言されたプロパティには、バックアップフィールド
インタフェースのプロパティのデフォルトは抽象的で、初期化値は許可されず、インタフェースはプロパティ値を保存しません.インタフェースを実装するときはプロパティを書き換える必要があります.
2.3インタフェースの継承
Kotlinのインタフェースは継承可能で、Javaと似ています.メンバーにインプリメンテーションを提供したり、新しいメンバー(関数とプロパティ)を宣言したりできます.したがって、このようなインタフェースを実装するクラスは、実装されていないメンバーを書き換えるだけでよい.
クラスPeopleでは
ChildInterfaceインタフェースは
では、なぜクラスPeopleでは
同様に、
なぜChildInterfaceは
ChildInterface自体がインタフェースであるため、
総じて、実装クラスは、実装されていない関数と属性を書き換える必要があります.
2.4インタフェース書き換えの競合
インタフェース書き換え競合とは,前述したクラス継承メソッドの競合と似ている.1つのサブクラスで複数の親インタフェースが実装され、異なる親インタフェースには同じメソッド名があり、サブクラスの実装時に競合し、呼び出された親の実装を確認できません.
インタフェースA、Bは、関数
しかし、インタフェースAおよびBから特定の実装クラスDが派生する場合、複数のインタフェース継承のすべての方法を実装し、クラスDがどのように正確に実装されるべきかを指定する必要がある.同じ方法が複数ある場合、
インタフェースAおよびBの
印刷データは次のとおりです.
三、関数インタフェース
1つの抽象メソッドのみのインタフェースを関数インタフェースまたは単一の抽象メソッド(SAM)インタフェースと呼ぶ.関数インタフェースには、いくつかの非抽象メンバーがありますが、1つの抽象メンバーのみが使用できます.
Kotlinで関数インタフェースを宣言するには、
3.1 SAM変換
Kotlin 1.4リリースでは、関数インタフェースでSAM変換を使用してLambda式を使用することで、コードをより簡潔に読み取ることができます.
「SAM変換」とは何ですか?
SAM変換、すなわちSingle Abstract Method Conversionsは、単一の非デフォルト抽象メソッドインタフェースのみに対する変換であり、条件を満たすインタフェースについては
関数インタフェースを実装するクラスを手動で作成するのではなく、Lambda式を使用できます.SAM変換により、Kotlinは、インタフェースの単一の方法の署名と一致する任意のLambda式を、インタフェースを実装するクラスのインスタンスに変換することができる.
たとえば、次の関数インタフェースを示します.
SAM変換前のこのインタフェースの実現方法:
KotlinのSAM変換を利用することで、以下の等価コードを書くことができます.
単純なLambda式は、多くの不要なコードを簡略化します.
印刷データは次のとおりです.
もちろん、Javaインタフェースに対してSAM変換を使用することもできます.
3.2関数インタフェースとタイプ別名
関数インタフェースとタイプ別名は、異なる目的で使用されます.タイプ別名は既存のタイプの名前にすぎません.新しいタイプは作成されませんが、関数インタフェースは作成できます.
タイプ別名には1つのメンバーしかありませんが、関数インタフェースには複数の非抽象メンバーと1つの抽象メンバーがあります.関数インタフェースは、他のインタフェースを実装および拡張することもできます.
以上のように、関数インタフェースはタイプ別名よりも柔軟であり、提供される機能もより多い.
これで、本文は終わります!
ソースアドレス:https://github.com/FollowExcellence/KotlinDemo-masterオリジナルの著作権を尊重してください.転載は出典を明記してください.https://blog.csdn.net/m0_37796683/article/details/107964620ありがとう!
一、概説
Kotlinのインタフェースは、抽象的なメソッドの宣言を含んでもよいし、メソッド実装を含んでもよい.インタフェースと抽象クラスの違いは、インタフェースがステータスを格納できないことです.これらは属性を持つことができますが、これらの属性は抽象的であるか、アクセサ実装を提供する必要があります.同時にKotlin 1.4バージョンからインタフェースのSAM変換をサポートしています.
KotlinのインタフェースはJava 8と同様で、
interface
キーワードを使用してインタフェースを定義し、デフォルトの実装を許可します. interface MyInterface {
fun share() // , abstract
fun invite() {// , abstract
println("invite()")//
}
}
インタフェースでインプリメンテーションが提供されていない方法のデフォルトは
abstract
修飾であり、インプリメンテーションが提供されるのはabstract
修飾ではない.サブクラスは抽象メンバーを書き換える必要があります.二、インタフェースの使用
2.1実装インタフェース
1つのクラスまたはオブジェクトは、1つまたは複数のインタフェースを実装することができる.KotlinではJavaのように
implements
のキーワード実装を提供するのではなく,コロン:
で表され,実装が必要なインタフェース名が後に続く. class Student : MyInterface {
override fun share() {// abstract , , invite() ,
//TODO
println("share()")
}
}
//
var student = Student()
student.share()
student.invite()
印刷データは次のとおりです.
share()
invite()
abstract
修飾の方法はサブクラスで書き直さなければなりません.もちろん、abstract
修飾の方法はありません.書き換えて自分の実現を提供することもできます.2.2インタフェースのプロパティ
インタフェースでプロパティを宣言したり、インタフェースで宣言したプロパティを抽象的にしたり、アクセサに実装したりすることができます.インタフェースで宣言されたプロパティには、バックアップフィールド
field
は使用できません.したがって、インタフェースで宣言されたアクセサは、バックアップフィールドを参照できません. interface MyInterface {
abstract val name: String // abstract
val type: Int
// get , field, abstract
get() = 10
// var age: Int // , field
// get() = field
// var sex: String = " "//
}
class Student : MyInterface {
override val name: String //abstract
get() = "Android"
}
インタフェースのプロパティのデフォルトは抽象的で、初期化値は許可されず、インタフェースはプロパティ値を保存しません.インタフェースを実装するときはプロパティを書き換える必要があります.
2.3インタフェースの継承
Kotlinのインタフェースは継承可能で、Javaと似ています.メンバーにインプリメンテーションを提供したり、新しいメンバー(関数とプロパティ)を宣言したりできます.したがって、このようなインタフェースを実装するクラスは、実装されていないメンバーを書き換えるだけでよい.
//
interface BaseInterface {
val name: String // ,
fun send1() // ,
fun send2() {// ,
println("send2()")
}
}
// : BaseInterface, name
interface ChildInterface : BaseInterface {
val childName: String // ,
override val name: String // BaseInterface name
get() = "Android"
}
// : ChildInterface
class People : ChildInterface {
override val childName: String // ChildInterface
get() = "Kotlin"
override fun send1() {// BaseInterface
println("send1()")
}
}
クラスPeopleでは
childName
を実現しなければならないが、name
を実現していないのはなぜか.ChildInterfaceインタフェースは
name
を書き換えたため、属性name
は抽象的ではなく、クラスPeopleでは実現する必要はありません.childName
はChildInterfaceで実装を提供していないが抽象的であるため、Peopleでは書き換え、実装を提供しなければならない.では、なぜクラスPeopleでは
send1()
を実現しなければならず、send2()
を実現しなかったのでしょうか.同様に、
send1()
はBaseInterfaceで実装を提供していないため、ChildInterfaceでも実装を提供していないため、抽象的であり、すべてPeopleで書き換え、実装を提供しなければならない.send2()
はBaseInterfaceで実装を提供しており、抽象的ではなく、書き直さなければならないものではありません.なぜChildInterfaceは
send1()
を実現せずにクラスPeopleで実現しなければならないのですか?ChildInterface自体がインタフェースであるため、
abstract
のメンバーを提供することができ、send1()
は抽象的であり、Peopleは特定の実装クラスであり、Peopleが抽象クラスでない限り、親インタフェースで実装されていない方法と属性を実装しなければならない.総じて、実装クラスは、実装されていない関数と属性を書き換える必要があります.
2.4インタフェース書き換えの競合
インタフェース書き換え競合とは,前述したクラス継承メソッドの競合と似ている.1つのサブクラスで複数の親インタフェースが実装され、異なる親インタフェースには同じメソッド名があり、サブクラスの実装時に競合し、呼び出された親の実装を確認できません.
interface A {
fun foo() {// ,
println("A:foo()")
}
fun bar()// ,
}
interface B {
fun foo() {// ,
println("B:foo()")
}
fun bar() {// ,
println("B:bar()")
}
}
// , A
class C : A {
override fun bar() {//A bar() , , ,
println("C:bar()")
}
}
// , A, B
class D : A, B {
// bar(), A bar()
override fun bar() {
super<B>.bar() // B bar(), A bar() , ,
}
// A B foo() , D , A foo() B foo() , Kotlin
override fun foo() {
super<A>.foo()// A foo()
super<B>.foo()// B foo()
}
}
インタフェースA、Bは、関数
foo()
およびbar()
を宣言し、いずれもfoo()
がデフォルトで実装されているが、インタフェースBのbar()
のみがデフォルトで実装されており、インタフェースAのbar()
はデフォルトで実装されておらず、デフォルトでは抽象的である.インタフェースAで特定のインプリメンテーションクラスCを派生させる場合、bar()
を書き換え、インプリメンテーションを提供する必要がある.上のclass Cのようです.しかし、インタフェースAおよびBから特定の実装クラスDが派生する場合、複数のインタフェース継承のすべての方法を実装し、クラスDがどのように正確に実装されるべきかを指定する必要がある.同じ方法が複数ある場合、
super
を使用して親クラスのインプリメンテーションを選択的に呼び出す方法を書き換える必要があります.上のclass Dのようです.インタフェースAおよびBの
foo()
メソッドはいずれもデフォルト実装を提供しているが、名前は同じサブクラスDに競合をもたらし、呼び出しがAのfoo()
実装であるかBのfoo()
実装であるかを確認できないため、Kotlinはサブクラスにfoo()
の書き換えを強制する.Aのbar()
はデフォルトのインプリメンテーションを提供していないため、強制的に書き換える必要がある. //
val d = D()
d.foo()
d.bar()
val c = C()
c.foo()
印刷データは次のとおりです.
A:foo()
B:foo()
B:bar()
C:bar()
三、関数インタフェース
1つの抽象メソッドのみのインタフェースを関数インタフェースまたは単一の抽象メソッド(SAM)インタフェースと呼ぶ.関数インタフェースには、いくつかの非抽象メンバーがありますが、1つの抽象メンバーのみが使用できます.
Kotlinで関数インタフェースを宣言するには、
fun
修飾子を使用してインタフェースを修飾します. // fun
fun interface KRunnable {
fun invoke()
}
3.1 SAM変換
Kotlin 1.4リリースでは、関数インタフェースでSAM変換を使用してLambda式を使用することで、コードをより簡潔に読み取ることができます.
「SAM変換」とは何ですか?
SAM変換、すなわちSingle Abstract Method Conversionsは、単一の非デフォルト抽象メソッドインタフェースのみに対する変換であり、条件を満たすインタフェースについては
SAM Type
と呼ばれ、KotlinではLambda式を直接使用して表すことができ、Lambdaが表す関数クラスがインタフェースのメソッドと一致することを前提としている.関数インタフェースを実装するクラスを手動で作成するのではなく、Lambda式を使用できます.SAM変換により、Kotlinは、インタフェースの単一の方法の署名と一致する任意のLambda式を、インタフェースを実装するクラスのインスタンスに変換することができる.
たとえば、次の関数インタフェースを示します.
fun interface IntAction {
fun check(int: Int): Boolean
}
SAM変換前のこのインタフェースの実現方法:
//
var isEvent = object : IntAction {
override fun check(int: Int): Boolean {
return int % 2 == 0
}
}
KotlinのSAM変換を利用することで、以下の等価コードを書くことができます.
var isEvent = IntAction { it % 2 == 0 }
単純なLambda式は、多くの不要なコードを簡略化します.
//
fun interface IntAction {
fun check(int: Int): Boolean
}
//Lambda
var isEvent2 = IntAction { it % 2 == 0 }
fun main() {
println("8 2 :${isEvent.check(8)}")
}
印刷データは次のとおりです.
8 2 :true
もちろん、Javaインタフェースに対してSAM変換を使用することもできます.
3.2関数インタフェースとタイプ別名
関数インタフェースとタイプ別名は、異なる目的で使用されます.タイプ別名は既存のタイプの名前にすぎません.新しいタイプは作成されませんが、関数インタフェースは作成できます.
タイプ別名には1つのメンバーしかありませんが、関数インタフェースには複数の非抽象メンバーと1つの抽象メンバーがあります.関数インタフェースは、他のインタフェースを実装および拡張することもできます.
以上のように、関数インタフェースはタイプ別名よりも柔軟であり、提供される機能もより多い.
これで、本文は終わります!
ソースアドレス:https://github.com/FollowExcellence/KotlinDemo-masterオリジナルの著作権を尊重してください.転載は出典を明記してください.https://blog.csdn.net/m0_37796683/article/details/107964620ありがとう!