Kotlinのクラス – Kotlinのコンストラクタ
このチュートリアルでは、Kotlinのオブジェクト指向プログラミングの概念について説明します。Kotlinのクラスについて詳しく説明します。また、Kotlinのコンストラクタ、アクセス修飾子、抽象クラスについても説明します。
Kotlinのクラス
class FirstClass {
}
次の方法でクラスのインスタンスがインスタンス化されます。
val firstClass = FirstClass()
var new = FirstClass() //here new is the name of the var.
Javaとは異なり、Kotlinではnewはキーワードではありません。Kotlinでは、クラスはデフォルトでfinalとなります。したがって、上記の定義のJava版は、以下のようなものになります。
public final class FirstClass {
}
したがって、Kotlinのクラスはデフォルトでは継承できません。クラスを非finalにするには、キーワード「open」を追加する必要があります。
open class Me{
}
他の人々がこのクラスを継承するのを許可するために、オープンな注釈があります。
Kotlin クラスの例
いくつかの関数とプロパティを持つクラスを作成しましょう。そのクラスの関数やプロパティにアクセスする方法を見ていきます。さらに、メンバープロパティの設定方法も見ていきましょう。
class User {
var loggedIn: Boolean = false
val cantChangeValue = "Hi"
fun logOn() {
loggedIn = true
}
fun logOff() {
loggedIn = false
}
}
fun main(args: Array<String>) {
val user = User()
println(user.loggedIn) //false
user.logOn()
println(user.loggedIn) //true
user.logOff()
println(user.loggedIn) //false
user.cantChangeValue = "Hey" //won't compile. Can't modify a final variable.
}
メインの機能はTest.ktクラスに属しています。 メンバーや関数にアクセスするためには、ドット演算子を使用する必要があります。valプロパティはドット演算子を使用して再設定することはできません。
Kotlinのinit
以下のように、Kotlinのinitブロックが定義されています。
class User {
init{
print("Class instance is initialised.")
}
var loggedIn: Boolean = false
val cantChangeValue = "Hi"
fun logOn() {
loggedIn = true
}
fun logOff() {
loggedIn = false
}
}
クラスのインスタンス化時に、initブロック内のコードが最初に実行されます。initブロックは、次に示すような任意のコンストラクタでクラスがインスタンス化されるたびに実行されます。クラス内には複数の初期化ブロックを記述することができます。以下に示すように、これらは順次実行されます。
class MultiInit(name: String) {
init {
println("First initializer block that prints ${name}")
}
init {
println("Second initializer block that prints ${name.length}")
}
}
fun main(args: Array<String>) {
var multiInit = MultiInit("Kotlin")
}
//Following is printed in the log console.
//First initializer block that prints Kotlin
//Second initializer block that prints 6
以下のように、Kotlinのクラスでは、also関数を使用して宣言自体でプロパティを出力することができます。
class MultiInit(name: String) {
val firstProperty = "First property: $name".also(::println)
init {
println("First initializer block that prints ${name}")
}
val secondProperty = "Second property: ${name.length}".also(::println)
init {
println("Second initializer block that prints ${name.length}")
}
}
fun main(args: Array<String>) {
var multiInit = MultiInit("Kotlin")
}
//Following gets printed.
//First property: Kotlin
//First initializer block that prints Kotlin
//Second property: 6
//Second initializer block that prints 6
Kotlinのコンストラクタ
Kotlinのコンストラクタは特別なメンバー関数であり、プロパティを初期化するために使用されます。KotlinのコンストラクタはJavaと比較して、異なる書き方・構造を持っています。デフォルトでは、以下に示すようにクラスには空のコンストラクタがあります。
class Student {
var name: String
val age : Int
init {
name = "Anupam"
age = 24
}
init {
name = "Anupam Chugh"
//age = 26
}
}
fun main(args: Array<String>) {
val student = Student()
println("${student.name} age is ${student.age}")
student.name = "Your"
//student.age = 26 //won't compile. age is val
println("${student.name} age is ${student.age}")
}
//Following is printed on the console:
//Anupam Chugh age is 24
//Your age is 24
プライマリコンストラクター
以下のように、Kotlinの主要なコンストラクターはクラスヘッダー内で定義されます。
class User(var name: String, var isAdmin: Boolean) {
init {
name = name + " @ JournalDev.com"
println("Author Name is $name. Is Admin? $isAdmin")
}
}
主なコンストラクタの定義はクラスヘッダの内部に記述します。コンストラクタ自体でプロパティの型(val/var)を定義しています。注意:明示的にvarと指定されていない限り、コンストラクタ引数はデフォルトでvalとなります。
class User(name: String, isAdmin: Boolean)
上記のコードでは、nameとisAdminの両方を再割り当てすることはできません。また、以下に示すように、クラスのメンバープロパティにコンストラクタの引数を割り当てることもできます。
class User(name: String, val isAdmin: Boolean) {
var username = name
val _isAdmin = isAdmin
init {
username= username + " @ JournalDev.com"
println("Author Name is $name. Is Admin? $_isAdmin")
}
}
fun main(args: Array<String>) {
var user = User("Anupam",false)
user.isAdmin = true //won't compile since isAdmin is val
user._isAdmin = true //won't compile. Same reason.
user = User("Pankaj",true)
}
//Following is printed in the log console.
//Author Name is Anupam. Is Admin? false
//Author Name is Pankaj. Is Admin? true
Kotlinのコンストラクタのデフォルト値
Kotlinでは、以下に示すように、コンストラクター自体でデフォルト値を指定することができます。
class User(name: String, var website: String = "JournalDev") {
init {
println("Author $name writes at $website")
}
init {
website = website + ".com"
println("Author $name writes at $website")
}
}
fun main(args: Array<String>) {
var user = User("Anupam","JournalDev")
user = User("Pankaj","JournalDev")
}
//Following is printed on the console:
//Author Anupam writes at JournalDev
//Author Anupam writes at JournalDev.com
//Author Pankaj writes at JournalDev
//Author Pankaj writes at JournalDev.com
副次的なコンストラクタ
セカンダリコンストラクターは、キーワード「constructor」を前置して、クラスの本体内に記述されます。以下の例は、同じことを実証しています。
class Student {
var name: String
val age : Int
constructor(name: String, age: Int)
{
this.name = name
this.age = age
}
fun printDetails()
{
println("Name is $name and Age is $age")
}
}
fun main(args: Array<String>) {
var student = Student("Anupam", 24)
student.printDetails()
}
//Following is printed in the console.
//Name is Anupam and Age is 24
セカンダリコンストラクタの最も一般的な使用方法は、クラスを異なる方法で初期化する必要があるときにサブクラスで発生します。もしクラスにプライマリコンストラクタが含まれている場合、セカンダリコンストラクタはその宣言でそれを参照しなければなりません。このキーワードを使って宣言が行われます。
class Student(var name: String, val age: Int) {
var skill: String
init {
skill = "NA"
}
constructor(name: String, age: Int, skill: String) : this(name, age) {
this.skill = skill
}
fun printDetails() {
if (skill.equals("NA"))
println("Name is $name and Age is $age")
else
println("Name is $name and Age is $age Skill is $skill")
}
}
//Following is printed in the log console:
//Name is Anupam and Age is 24
//Name is Anupam and Age is 24 Skill is Kotlin
初期化ブロックは、メンバープロパティスキルを初期化するために使用されます。セカンダリコンストラクタは、プライマリコンストラクタに this を使用して委譲します。
カスタムのゲッターとセッター
これまで、クラスのプロパティには、クラスのインスタンス上でドット演算子を使用してアクセスおよび変更してきました。アクセスをカスタマイズする方法を見るために、セットとゲットの構文を使用しましょう。
class Name{
var post: String = "default"
set(value) {if(!post.isNotEmpty()) {
throw IllegalArgumentException(" Enter a valid name")
}
field = value
print(value)
}
}
fun main(args: Array<String>) {
var name = Name()
name.post = "Kotlin Classes"
name.post = ""
name.post = "Kotlin Data Classes Our Next Tutorial"
}
以下はログコンソールに表示されています。
Kotlin Classes
Exception in thread "main" java.lang.IllegalArgumentException: Enter a valid name
at Name.setPost(Test.kt:16)
at TestKt.main(Test.kt:78)
フィールド変数はセッターで以前の値を保存します。ゲッターを追加しましょう。
class Name{
var post: String = "default"
set(value) {if(!post.isNotEmpty()) {
throw IllegalArgumentException(" Enter a valid name")
}
field = value
}
get() {
return field.capitalize()
}
}
fun main(args: Array<String>) {
var name = Name()
name.post = "kotlin classes"
println(name.post)
name.post = "kotlin data Classes our next Tutorial"
println(name.post)
}
//Following is printed:
//Kotlin classes
//Kotlin data Classes our next Tutorial
capitalize()は文字列の最初の文字を大文字にします。注意:プロパティがvalの場合、セットメソッドはコンパイルされません。
Kotlinの可視性修飾子
- Public : Any class, function, property, interface, or object that has this modifier is visible and can be accessed from anywhere.
- Private: A class/function defined with this modifier can be only accessed within the same file. A member/property in a class/function with this modifier can be only accessed within that block.
- Protected : This modifier is same as private, except that it allows visibility and access within subclasses.
- Internal: A class/interface/function with this modifier is accessible only within the same module.
コンストラクタにも可視性修飾子が適用されます。プライマリコンストラクタに修飾子を割り当てるには、クラスヘッダーのコンストラクタと一緒にキーワード「constructor」を指定する必要があります。
class Student private constructor (var name: String, val age: Int) {
var skill: String
init {
skill = "NA"
}
constructor(name: String, age: Int, skill: String) : this(name, age) {
this.skill = skill
}
fun printDetails() {
if (skill.equals("NA"))
println("Name is $name and Age is $age")
else
println("Name is $name and Age is $age Skill is $skill")
}
}
fun main(args: Array<String>) {
var student = Student("Anupam",24,"Kotlin")
student.printDetails()
}
//prints
//Name is Anupam and Age is 24 Skill is Kotlin
上記のコードでは、プライベートなコンストラクタはクラスの外部から呼び出すことができません。別の関数内でのみ、セカンダリコンストラクタを使用してクラスをインスタンス化することができます。
抽象的なKotlinクラス
Javaと同様に、Kotlinではabstractキーワードを使用して抽象クラスを宣言します。抽象クラスはインスタンス化できませんが、サブクラスによって継承されることができます。デフォルトでは、抽象クラスのメンバーは非抽象ですが、明示的に指定しない限りです。
abstract class Person(name: String) {
init {
println("Abstract Class. init block. Person name is $name")
}
abstract fun displayAge()
}
class Teacher(name: String): Person(name) {
var age : Int
init {
age = 24
}
override fun displayAge() {
println("Non-abstract class displayAge function overridden. Age is $age")
}
}
fun main(args: Array<String>) {
val person = Teacher("Anupam")
person.displayAge()
}
//Following is printed in the console.
//Abstract Class. init block. Person name is Anupam
//Non-abstract class. Age is 24
注記:抽象クラスはデフォルトではオープンです。そのため、サブクラス化を許可するためのオープン修飾子の追加は必要ありません。オーバーライドキーワードはサブクラスでメソッドをオーバーライドするために使用されます。このチュートリアルでは、Kotlinクラスの基本的な内容をカバーしました。データクラス、シールドクラス、継承など、まだまだたくさんの要素があります。これらについては、今後のチュートリアルでカバーします。参考文献:Kotlinドキュメント