Kotlinのクラスとオブジェクト
クラス定義
Kotlinクラスには、コンストラクターと初期化コードブロック、関数、プロパティ、内部クラス、オブジェクト宣言を含めることができます。
Kotlinは、キーワードclassを使用してクラスを宣言し、その後にクラス名を付けます
class Runoob { // 类名为 Runoob
// 大括号内是类体构成
}
空のクラスを定義することもできます
class Empty
メンバー関数はクラスで定義できます
class Runoob() {
fun foo() { print("Foo") } // 成员函数
}
クラス属性
属性定義
クラスのプロパティは、キーワードvarを使用して可変として宣言できます。それ以外の場合は、読み取り専用キーワードvalを使用して不変として宣言できます。
class Runoob {
var name: String = ……
var url: String = ……
var city: String = ……
}
コンストラクターを使用して、通常の関数のようなクラスインスタンスを作成できます
val site = Runoob() // Kotlin 中没有 new 关键字
属性を使用するには、名前で参照するだけです
site.name // 使用 . 号来引用
site.url
Koltinのクラスには、1次コンストラクターと1つ以上の2次コンストラクターを含めることができます。1次コンストラクターはクラスヘッダーの一部であり、クラス名の後にあります。
class Person constructor(firstName: String) {}
メインコンストラクターにアノテーションがなく、可視性修飾子がない場合は、コンストラクターキーワードを省略できます。
class Person(firstName: String) {
}
ゲッター和セッター
属性宣言の完全な構文
var <propertyName>[: <PropertyType>] [= <property_initializer>]
[<getter>]
[<setter>]
ゲッターとセッターはどちらもオプションです
初期化ステートメントまたはクラスのメンバー関数から属性タイプを推測できる場合は、タイプを省略できます。valは読み取り専用であるため、setter関数を設定できません。
var allByDefault: Int? // 错误: 需要一个初始化语句, 默认实现了 getter 和 setter 方法
var initialized = 1 // 类型为 Int, 默认实现了 getter 和 setter
val simple: Int? // 类型为 Int ,默认实现 getter ,但必须在构造函数中初始化
val inferredType = 1 // 类型为 Int 类型,默认实现 getter
インスタンス
次の例では、2つの変数変数lastNameとnoを含むPersonクラスを定義します。LastNameはgetterメソッドを変更し、noはsetterメソッドを変更します。
class Person {
var lastName: String = "zhang"
get() = field.toUpperCase() // 将变量赋值后转换为大写
set
var no: Int = 100
get() = field // 后端变量
set(value) {
if (value < 10) { // 如果传入的值小于 10 返回该值
field = value
} else {
field = -1 // 如果传入的值大于等于 10 返回 -1
}
}
var heiht: Float = 145.4f
private set
}
// 测试
fun main(args: Array<String>) {
var person: Person = Person()
person.lastName = "wang"
println("lastName:${person.lastName}")
person.no = 9
println("no:${person.no}")
person.no = 20
println("no:${person.no}")
}
出力結果
lastName:WANG
no:9
no:-1
Kotlinのクラスにフィールドを含めることはできません。バッキングフィールド(バックエンド変数)メカニズムを提供し、代替フィールドはfieldキーワードで宣言され、fieldキーワードは、上記の例のように、属性アクセサーにのみ使用できます。
空でないプロパティは、定義時に初期化する必要があります。Kotlinは、lateinitキーワードを使用してプロパティを記述することにより、後で初期化できるソリューションを提供します。
public class MyTest {
lateinit var subject: TestSubject
@SetUp fun setup() {
subject = TestSubject()
}
@Test fun test() {
subject.method() // dereference directly
}
}
メインコンストラクター
メインコンストラクターにコードを含めることはできません。初期化コードは初期化コードセグメントに配置でき、初期化コードセグメントはinitキーワードをプレフィックスとして使用します。
class Person constructor(firstName: String) {
init {
println("FirstName is $firstName")
}
}
注:メインコンストラクターのパラメーターは、初期化コードセグメントで使用できます。また、クラス本体nで定義された属性初期化コードでも使用できます。簡潔な構文で、メインコンストラクターを介して属性を定義し、属性値を初期化できます(varまたはvalにすることができます)
class People(val firstName: String, val lastName: String) {
//...
}
コンストラクターに注釈または可視性修飾子がある場合は、コンストラクターキーワードが必要であり、注釈と修飾子はその前に配置する必要があります
インスタンス
Runoobクラスを作成し、コンストラクターを介してWebサイト名を渡します
class Runoob constructor(name: String) { // 类名为 Runoob
// 大括号内是类体构成
var url: String = "http://www.runoob.com"
var country: String = "CN"
var siteName = name
init {
println("初始化网站名: ${name}")
}
fun printTest() {
println("我是类的函数")
}
}
fun main(args: Array<String>) {
val runoob = Runoob("菜鸟教程")
println(runoob.siteName)
println(runoob.url)
println(runoob.country)
runoob.printTest()
}
出力結果
初始化网站名: 菜鸟教程
菜鸟教程
http://www.runoob.com
CN
我是类的函数
サブコンストラクター
クラスには、コンストラクターをプレフィックスとして付ける必要があるセカンダリコンストラクターを含めることもできます。
class Person {
constructor(parent: Person) {
parent.children.add(this)
}
}
クラスに1次コンストラクターがある場合、各2次コンストラクターは、別の2次コンストラクターを介して1次コンストラクターを直接または間接的にプロキシする必要があります。このキーワードを使用して、同じクラスの別のコンストラクターをプロキシします
class Person(val name: String) {
constructor (name: String, age:Int) : this(name) {
// 初始化...
}
}
非抽象クラスがコンストラクター(一次コンストラクターまたは二次コンストラクター)を宣言しない場合、パラメーターのないコンストラクターが生成されます。コンストラクターはパブリックです。クラスにパブリックコンストラクターを持たせたくない場合は、空のメインコンストラクターを宣言する必要があります
class DontCreateMe private constructor () {
}
注:JVM仮想マシンでは、メインコンストラクターのすべてのパラメーターにデフォルト値がある場合、コンパイラーはパラメーターなしで追加のコンストラクターを生成し、このコンストラクターはデフォルト値を直接使用します。これにより、Kotlinは、パラメーターのないコンストラクターを使用してクラスインスタンスを作成するJacksonやJPAなどのライブラリを簡単に使用できます。
class Customer(val customerName: String = "")
インスタンス
class Runoob constructor(name: String) { // 类名为 Runoob
// 大括号内是类体构成
var url: String = "http://www.runoob.com"
var country: String = "CN"
var siteName = name
init {
println("初始化网站名: ${name}")
}
// 次构造函数
constructor (name: String, alexa: Int) : this(name) {
println("Alexa 排名 $alexa")
}
fun printTest() {
println("我是类的函数")
}
}
fun main(args: Array<String>) {
val runoob = Runoob("菜鸟教程", 10000)
println(runoob.siteName)
println(runoob.url)
println(runoob.country)
runoob.printTest()
}
出力結果
初始化网站名: 菜鸟教程
Alexa 排名 10000
菜鸟教程
http://www.runoob.com
CN
我是类的函数
抽象クラス
抽象化は、オブジェクト指向プログラミングの特徴の1つであり、クラス自体、またはクラスの一部のメンバーは、抽象として宣言できます。クラス内の抽象メンバーの具体的な実現はありません。
注:抽象クラスまたは抽象メンバーにオープンアノテーションをマークする必要はありません
open class Base {
open fun f() {}
}
abstract class Derived : Base() {
override abstract fun f()
}
ネストされたクラス
クラスを他のクラスにネストできます。次の例を参照してください
class Outer { // 外部类
private val bar: Int = 1
class Nested { // 嵌套类
fun foo() = 2
}
}
fun main(args: Array<String>) {
val demo = Outer.Nested().foo() // 调用格式:外部类.嵌套类.嵌套类方法/属性
println(demo) // == 2
}
インナークラス
内部クラスは、innerキーワードで表されます。
内部クラスは外部クラスのオブジェクトへの参照を持つため、内部クラスは外部クラスのメンバープロパティとメンバー関数にアクセスできます。
class Outer {
private val bar: Int = 1
var v = "成员属性"
/**嵌套内部类**/
inner class Inner {
fun foo() = bar // 访问外部类成员
fun innerTest() {
var o = this@Outer //获取外部类的成员变量
println("内部类可以引用外部类的成员,例如:" + o.v)
}
}
}
fun main(args: Array<String>) {
val demo = Outer().Inner().foo()
println(demo) // 1
val demo2 = Outer().Inner().innerTest()
println(demo2) // 内部类可以引用外部类的成员,例如:成员属性
}
あいまいさを排除するために、外部スコープからこれにアクセスするには、this @ labelを使用します。ここで、@ labelは、このソースを参照するラベルです。
匿名の内部クラス
オブジェクト式を使用して匿名の内部クラスを作成する
class Test {
var v = "成员属性"
fun setInterFace(test: TestInterFace) {
test.test()
}
}
/**
* 定义接口
*/
interface TestInterFace {
fun test()
}
fun main(args: Array<String>) {
var test = Test()
/**
* 采用对象表达式来创建接口对象,即匿名内部类的实例。
*/
test.setInterFace(object : TestInterFace {
override fun test() {
println("对象表达式创建匿名内部类的实例")
}
})
}
ここでオブジェクトに特に注意してください:TestInterFace。このオブジェクトはKotlinのキーワードです。匿名の内部クラスを実装するには、objectキーワードを使用する必要があります。他の単語を自由に置き換えることはできません。覚えておいてください。
クラス修飾子
クラス修飾子には、classModifierとaccessModifierが含まれます
classModifier:クラス自体の特性を示すクラス属性修飾子
abstract // 抽象类
final // 类不可继承,默认属性
enum // 枚举类
open // 类可继承,类默认是final的
annotation // 注解类
accessModifier:アクセス修飾子
private // 仅在同一个文件中可见
protected // 同一个文件中或子类可见
public // 所有调用的地方都可见
internal // 同一个模块中可见
インスタンス
// 文件名:example.kt
package foo
private fun foo() {} // 在 example.kt 内可见
public var bar: Int = 5 // 该属性随处可见
internal val baz = 6 // 相同模块内可见