Kotlinスタートブック(赤べこ本) 第10章 の 写経
list 10.1 interface, list 10.2 interface の実装例
// list 10.1
interface Greeter {
val language: String
fun sayHello (target : String )
}
// list 10.2 `:` の後に interface 名
class EnglishGreeter : Greeter {
// `override`
override val language = " English"
// `override`
override fun sayHello (target : String ) {
println (" Hello, $target !" )
}
}
fun main (args : Array <String >) {
val g: Greeter = EnglishGreeter ()
println (g.language) // English
g.sayHello(" Kotlin" ) // Hello, Kotlin!
}
list 10.3 複数の interface の実装
open class Superclass
interface Foo
interface Bar
class MyClassa : Superclass (), Foo, Bar
list 10.4 同一シグニチャ の メソッドの実装
interface Foo {
fun execute ()
}
interface Bar {
fun execute ()
}
class FooBar : Foo , Bar {
// `override`
override fun execute () {
println (" FooBar" )
}
}
fun main (args : Array <String >) {
var f: Foo = FooBar ()
var b: Bar = FooBar ()
f.execute() // FooBar
b.execute() // FooBar
}
list 10.5 interface と class で 同一シグニチャ メソッド
interface Foo {
fun execute ()
}
open class Superclass {
fun execute () {
println (" Superclass" )
}
}
class FooSubclass : Superclass (), Foo
fun main (args : Array <String >) {
val f: Foo = FooSubclass ()
f.execute() // Superclass
}
list 10.6 実装を持った 2つの interface の実装, list 10.7 interface Hoge
の実装を使用
// list 10.6
interface Hoge {
fun execute () {
println (" Hoge" )
}
}
interface Fuga {
fun execute () {
println (" Fuga" )
}
}
//
// list 10.6 コンパイルエラー. 複数の実装 -> 曖昧さが発生
//
// Class 'HogeFuga' must override public open fun execute():Unit defined in Hoge
// because it inherits multiple interface methods of it
//
class HogeFuga : Hoge , Fuga
// 追記(単独で implement するのは問題無い)
class Hoge2 : Hoge // OK
class Fuga2 : Fuga // OK
//
// list 10.7 `Hoge` の実装を使用
//
class HogeFuga2 : Hoge , Fuga { // OK
// `override`
override fun execute () {
super <Hoge >.execute() // `super<interface または class>.method()`
}
}
fun main (args : Array <String >) {
val h: Hoge = HogeFuga2 ()
val f: Fuga = HogeFuga2 ()
h.execute() // Hoge
f.execute() // Hoge
}
interface Foo {
fun aaa ()
fun bbb ()
}
interface Bar : Foo {
override fun aaa () {}
fun ccc ()
}
class Baz : Bar {
override fun bbb () {}
override fun ccc () {}
}
list 10.9 interface Greeter
, list 10.10 class JapaneseGreeterWithRecording
// list 10.9
interface Greeter {
fun sayHello (target : String )
fun sayHello ()
}
// 赤べこ本には記述無いが, 多分こんな実装
open class JapaneseGreeter : Greeter {
override fun sayHello (target : String ) {
println (" こんにちは, ${target} さん!" )
}
override fun sayHello () {
sayHello(" 匿名" )
}
}
//
// list 10.10 継承
//
class JapaneseGreeterWithRecording : JapaneseGreeter () {
private val _targets : MutableSet <String > = mutableSetOf ()
val targets: Set <String >
get() = _targets
// `override`
override fun sayHello (target : String ) {
_targets + = target
super .sayHello(target) // superclass の 実装を利用
}
}
fun main (args : Array <String >) {
val greeter = JapaneseGreeterWithRecording ()
greeter.sayHello(" うらがみ" ) // こんにちは, うらがみさん!
greeter.sayHello(" がくぞ" ) // こんにちは, がくぞさん!
println (greeter.targets) // [うらがみ, がくぞ]
greeter.sayHello(" ***" ) // こんにちは, ***さん!
greeter.sayHello() // こんにちは, 匿名さん!
println (greeter.targets) // [うらがみ, がくぞ, ***, 匿名] // "匿名" も記録されている <- 期待しない動作
}
sayHello()
呼び出し時の "匿名" も記録されている <- 期待しない動作
list 10.11 delegation を行うバージョン
// list 10.9
interface Greeter {
fun sayHello (target : String )
fun sayHello ()
}
open class JapaneseGreeter : Greeter {
override fun sayHello (target : String ) {
println (" こんにちは, ${target} さん!" )
}
override fun sayHello () {
sayHello(" 匿名" )
}
}
//
// list 10.11 `JapaneseGreeter` の 継承 をやめて `Greeter` を実装
//
class JapaneseGreeterWithRecording : Greeter {
// <委譲先>
private val g: Greeter = JapaneseGreeter ()
private val _targets : MutableSet <String > = mutableSetOf ()
val targets: Set <String >
get() = _targets
// <追加>
override fun sayHello () {
g.sayHello() // <委譲>
}
override fun sayHello (target : String ) {
_targets + = target
// <変更>
// super.sayHello(target)
g.sayHello(target) // <委譲>
}
}
fun main (args : Array <String >) {
val greeter = JapaneseGreeterWithRecording ()
greeter.sayHello(" うらがみ" ) // こんにちは, うらがみさん!
greeter.sayHello(" がくぞ" ) // こんにちは, がくぞさん!
println (greeter.targets) // [うらがみ, がくぞ]
greeter.sayHello(" ***" ) // こんにちは, ***さん!
greeter.sayHello() // こんにちは, 匿名さん!
println (greeter.targets) // [うらがみ, がくぞ, ***] // "匿名" が記録されなくなった <- 期待する動作
}
list 10.12 class delegation を使った例
委譲先
必要な分だけ override すればok
// list 10.9
interface Greeter {
fun sayHello (target : String )
fun sayHello ()
}
open class JapaneseGreeter : Greeter {
override fun sayHello (target : String ) {
println (" こんにちは, ${target} さん!" )
}
override fun sayHello () {
sayHello(" 匿名" )
}
}
//
// list 10.12 委譲先 を constructor で受け取る && `by` で 委譲先を指定
//
class JapaneseGreeterWithRecording (private val g : Greeter ) : Greeter by g { // `by`
private val _targets : MutableSet <String > = mutableSetOf ()
val targets: Set <String >
get() = _targets
override fun sayHello (target : String ) {
_targets + = target
g.sayHello(target) // <委譲>
}
}
fun main (args : Array <String >) {
val greeter = JapaneseGreeterWithRecording (JapaneseGreeter ())
greeter.sayHello(" うらがみ" ) // こんにちは, うらがみさん!
greeter.sayHello(" がくぞ" ) // こんにちは, がくぞさん!
println (greeter.targets) // [うらがみ, がくぞ]
greeter.sayHello(" ***" ) // こんにちは, ***さん!
greeter.sayHello() // こんにちは, 匿名さん!
println (greeter.targets) // [うらがみ, がくぞ, ***]
}