前回ã«ç¶ããä»åãKotlinã®ãªãã¸ã§ã¯ãæåã«é¢ããæ©è½ãç´¹ä»ãã¦ããããã¨æãã¾ãã
â»ä¸è¨URLã®ãµã¤ããåèã«ãã¾ãããè±èªãã¾ãã¯æè¡çãªç¥èãè³ãããå
容ã«èª¤ããå«ã¾ããããããããã¾ãã®ã§ããäºæ¿ãã ããã
â»æ¬ã¨ã³ããªã®8å²ã¯åèãµã¤ãã®ç¿»è¨³ã§ããæ®ãã®2å²ã¯ç§ã®è§£éã§å çãå¤æ´ãæ½ããæ§æã§ãã
åèãµã¤ã http://confluence.jetbrains.net/display/Kotlin/Classes+and+Inheritance
ãã¬ã¤ã
ãã¬ã¤ãï¼traitï¼ã¯æ¬è³ªçã«ã¯ã¡ã½ããæ¬ä½ãå«ãã¤ã³ã¿ãã§ã¼ã¹ã§ãï¼ã¡ã½ããã¯ä»»æï¼ã
ãã¬ã¤ãã®å®ç¾©ã¨ãã®å®è£
ã¯æ¬¡ã®ããã«è¡ãã¾ãã
trait Foo { open fun foo() } class Bar() : Foo { override fun foo() { } }
ãªã¼ãã©ã¤ãã®ã«ã¼ã«
ã¯ã©ã¹ããã®ç´è¿ã®ã¹ã¼ãã¼ã¯ã©ã¹ããåãã¡ã³ããè¤æ°å®è£ ããå ´åããã®ã¡ã³ãããªã¼ãã©ã¤ããç¬èªã®å®è£ ãæä¾ããªããã°ãªãã¾ãããã¹ã¼ãã¼ã¯ã©ã¹ã®å®è£ ã使ç¨ãããã¨ãã«ã¯ãsuperã¨å±±æ¬å¼§ï¼<>âããï¼ã使ãã¾ãã
open class A() { open fun msg() = "a" fun a() = "A" } trait B { open fun msg() = "b" //ãã¬ã¤ãã¯å ·è±¡ã¯ã©ã¹ãæã¦ã open fun b() = "B" } open class C() : A(), B { override fun msg() = super<A>.msg() + super<B>.msg() //ãã®é¢æ°ãå®è£ ããªãã¨ã³ã³ãã¤ã«ã¨ã©ã¼ã¨ãªã } class D() : C() { override fun msg() = super<A>.msg() //ããã¯ã¨ã©ã¼ã¨ãªããã¢ã¯ã»ã¹ã§ããã®ã¯ãããã¾ã§ç´è¿ã®ã¹ã¼ãã¼ã¯ã©ã¹ã®å®è£ ã«ã ã }
Aã¨Bã両æ¹ã¨ãç¶æ¿ããã®ã¯åé¡ããã¾ãããCã«ããã¦ãa()ãb()ããã£ãã²ã¨ã¤ã®å®è£ ããç¶æ¿ãã¦ããªãã®ã§ããããåé¡ããã¾ãããããããCã¯msg()ã®2ã¤ã®å®è£ ãç¶æ¿ãã¦ããã®ã§ãmsg()ããªã¼ãã©ã¤ãããªããã°ãªãã¾ããããããã¦ç¬èªã®å®è£ ãæä¾ãããã¨ã«ããææ§ããæé¤ãã¦ãã¾ãã
æ½è±¡ã¯ã©ã¹
Javaã®ããã«ãã¯ã©ã¹ããã®ã¡ã³ãã¯æ½è±¡ï¼abstractï¼ã¨ãã¦å®£è¨ãããã¨ãã§ãã¾ããæ½è±¡ã¡ã³ãã¯ããã®ã¯ã©ã¹ã«ããã¦ã¯å®è£ ãæã¡ã¾ããããããã£ã¦åå«ãæ½è±¡ã¡ã³ããç¶æ¿ããã¨ããããã¯å ·è±¡ã¡ã³ãã¨ãã¦ã«ã¦ã³ãããã¾ããã次ã®ã³ã¼ããè¦ã¦ãã ãã*1ã
abstract class A { abstract fun f() } trait B { open fun f() { } } class C() : A, B { // f()ããªã¼ãã©ã¤ãããå¿ è¦ã¯ããã¾ãã }
æ½è±¡ã¯ã©ã¹ã«ã¯openã¢ããã¼ã·ã§ã³ãä¸è¦ãªãã¨ã«æ³¨æãã¦ãã ãããè¨ãã¾ã§ããªãã®ã§ããæ½è±¡é¢æ°ã«ã¤ãã¦ãåæ§ã§ãã
次ã®ã³ã¼ãã®ããã«*2ãæ½è±¡ã§ã¯ãªãopenãªã¡ã³ããæ½è±¡ã¡ã³ãã¨ãã¦ãªã¼ãã©ã¤ãã§ãã¾ãã
open class Base { open fun f() {} } abstract class Derived : Base { override abstract fun f() }
ãªã¼ãã©ã¤ãå¯è½ãªããããã£ã¨ã¢ã¯ã»ãµ
é¢æ°ã ãã§ãªããããããã£ãopen宣è¨ã§ãã¾ããå®éã«ã¯ãããããã£ã®ã¢ã¯ã»ãµããªã¼ãã©ã¤ãå¯è½ã«ãªããã¨ãæå³ãã¦ãã¾ãã
open class Foo { open val prop : String get() = "foo" } class Bar : Foo { override val prop : String get() = "bar" }
ã¢ã¯ã»ãµã²ã¨ã¤ã²ã¨ã¤ã«openãoverrideãä»ãããã¨ãã§ãã¾ãã次ã®ã³ã¼ããè¦ã¦ãã ãã*3ã
open class Foo { var prop : String get() = "foo" open set(value) { } } class Bar : Foo { var prop : String override set(value) { prop = value } }
å§è²
委譲パターンï¼delegation patternï¼ã¯å ·è±¡ç¶æ¿ã®ä»£æ¿ã¨ãã¦è¯ãå®ç¸¾ããããKotlinã§ã¯ããããµãã¼ããã¦ãã¾ããã¤ã¾ããã®ããã®å®åã³ã¼ããæ¸ãå¿ è¦ãããã¾ããã次ã®ã³ã¼ã*4ã«ããã¦ãDrivedã¯ã©ã¹ã¯Baseãã¬ã¤ãã®ç¶æ¿ã¨ããã®publicã¡ã½ããã®å ¨ã¦ãæå®ãããªãã¸ã§ã¯ãã¸å§è²ãããã¨ããå¯è½ã§ãã
trait Base { fun print() } class BaseImpl(x : Int) : Base { val x = x override fun print() { print(this.x) } } class Derived(b : Base) : Base by b fun main(args : Array<String>) { val b = BaseImpl(10) Derived(b).print() // prints 10 }
Drivedã®ã¹ã¼ãã¼ã¯ã©ã¹ãªã¹ãã®byå¥ã¯ãbãDrivedã®ãªãã¸ã§ã¯ãå é¨ã«æ ¼ç´ããããã¨ã¨ãã³ã³ãã¤ã©ãbã¸è»¢éããBaseã®å ¨ã¦ã®ã¡ã½ãããçæãããã¨ã示ãã¦ãã¾ãã
ã¯ã©ã¹ãªãã¸ã§ã¯ã
Kotlinã§ã¯Javaã¨ç°ãªããã¯ã©ã¹ã¯éçã¡ã½ããï¼static methodï¼ãæã¦ã¾ãããå¤ãã®å ´åãåå空éã¬ãã«ã®é¢æ°ï¼namespace-level functionï¼ãããã®è¯ã代æ¿ãå½¢æãã¾ãããããã§ãªãå ´åãå°ãããã¾ããã¯ã©ã¹å é¨ï¼privateã¡ã³ãï¼ã«ã¢ã¯ã»ã¹ããå ´åã§ãã
ä¾ãã°Factory Methodパターンã«å¾ã£ãã³ã³ã¹ãã©ã¯ã¿ã®ç½®æã¯ãã³ã³ã¹ãã©ã¯ã¿ãprivateã«ããã³ã³ã¹ãã©ã¯ã¿ãå¼ã³åºãé¢æ°ãæä¾ãã¾ãããããããã®é¢æ°ãããã§åé¡ã«ãã¦ããããã«ã¯ã©ã¹ã®å¤å´ã«ç½®ããã¦ããããã³ã³ã¹ãã©ã¯ã¿ã«ä¸åã¢ã¯ã»ã¹ã§ãã¾ããã
ãã®åé¡ã«å¯¾å¿ããããï¼ã¾ãããã®ä»ã®èå³æ·±ãæ©è½ãæä¾ããããï¼ãKotlinã§ã¯ã¯ã©ã¹ãªãã¸ã§ã¯ãï¼class objectï¼ã¨ããæ¦å¿µãå°å ¥ãã¦ãã¾ãï¼ä»ã®è¨èªã«ãããæãè¿ãé¡ä¼¼ç©ã¯ãScalaã®Companion objectã§ãï¼ã大ã¾ãã«è¨ãã°ãCã¯ã©ã¹ã®ã¯ã©ã¹ãªãã¸ã§ã¯ãã¯Cã¨é¢é£ãããªãã¸ã§ã¯ãã§ãï¼オブジェクト宣言çãªæå³ã§ï¼ãã¯ã©ã¹ãªãã¸ã§ã¯ãã¯é¢é£ããã¯ã©ã¹å é¨ã«å®£è¨ãããã®ã§ããã®privateã¡ã³ãã«ã¢ã¯ã»ã¹ã§ããã®ã§ããCã®ã¯ã©ã¹ãªãã¸ã§ã¯ãã¯ï¼é常ã¯ï¼Cã®ã¤ã³ã¹ã¿ã³ã¹ã§ã¯ããã¾ãããä¾ã¨ãã¦æ¬¡ã®ã³ã¼ããè¦ã¦ãã ãã*5ã
class C() { class object { fun create() = C() } } fun main() { val c = C.create() // C denotes the class object here }
æåã«ããªãã¯ãããã¯ã©ã¹ã®éçã¡ã³ããã°ã«ã¼ãã³ã°ããæ£å½ãªæ¹æ³ã ã¨æãããç¥ãã¾ãããJavaã®ããã«ãã¯ã©ã¹ã¡ã³ãï¼éçã¡ã³ãï¼ã¨ã¤ã³ã¹ã¿ã³ã¹ã¡ã³ããæ··å¨ãããããªæ¹æ³ã¨æ¯ã¹ã¦ããããå®éã«ã¯ã両è ã®æ¯ãèãã«ã¯éè¦ãªéããããã¾ããã¯ã©ã¹ãªãã¸ã§ã¯ãã¯ã¹ã¼ãã¼ã¿ã¤ããæã¤ãã¨ãã§ãã¾ãã説æããããã次ã®ã³ã¼ã*6ãè¦ãã»ããç解ãæ©ãããç¥ãã¾ããã
abstract class Factory<out T> { fun create() : T } open class C() { class object : Factory<C> { override fun create() : C = C() } } fun main() { val factory = C // C denotes the class object val c = factory.create() }
注æï¼ã¯ã©ã¹ãªãã¸ã§ã¯ãã¯ç¶æ¿ã§ãã¾ããã
注æï¼ããªãã¯ã¯ã©ã¹ãªãã¸ã§ã¯ããKotlinã«ãããè¯ãã·ã³ã°ã«ãã³ã®å®è£
æ¹æ³ã ã¨æãããç¥ãã¾ããããKotlinのオブジェクト式とオブジェクト宣言 - 算譜王におれはなる!!!!ãè¦ã¦ãã ããã
ãã®æ©è½*7ã«é¢é£ãããã¹ããã©ã¯ãã£ã¹
Effective Java(Joshua Bloch著)
é
ç®16ï¼Favor composition over inheritance*8
é
ç®17ï¼Design and document for inheritance or else prohibit it*9
é
ç®18ï¼Prefer interfaces to abstract classes*10
ä»ã®è¨èªã«ãããé¡ä¼¼æ©è½
IDEã¯èªåçã«委譲メソッドを生成するã
Lombokプロジェクトã¯ãJavaã«ãããã¢ããã¼ã·ã§ã³ã§ã®å§è²ãå®è£ ãã¦ããã
Scalaã¯ãã¬ã¤ããæã£ã¦ããã
Groovyã¯CategoryとMixinãæã£ã¦ããã
*1:http://confluence.jetbrains.net/display/Kotlin/Classes+and+Inheritanceã®ãµã³ãã«ã³ã¼ããä¸é¨å¤æ´
*2:http://confluence.jetbrains.net/display/Kotlin/Classes+and+Inheritanceããå¼ç¨
*3:http://kotlin-demo.jetbrains.com/ã§è©¦ãã¨ã³ã³ãã¤ã«ã¨ã©ã¼ã¨ãªã£ã¦ãã¾ãã¾ãã
*4:http://confluence.jetbrains.net/display/Kotlin/Classes+and+Inheritanceã®ã³ã¼ããä¸é¨å¤æ´
*5:http://confluence.jetbrains.net/display/Kotlin/Classes+and+Inheritanceããå¼ç¨
*6:http://confluence.jetbrains.net/display/Kotlin/Classes+and+Inheritanceããå¼ç¨
*7:Kotlinã®ã¯ã©ã¹ãç¶æ¿ã«ã¾ã¤ããæ©è½ã®ãã¨ã
*8:é¦è¨³ï¼ç¶æ¿ããã³ã³ãã¸ã·ã§ã³ãé¸ã¶
*9:é¦è¨³ï¼ç¶æ¿ã®ããã«è¨è¨ããã³ææ¸åãããã§ãªããã°ç¶æ¿ãç¦æ¢ãã
*10:é¦è¨³ï¼æ½è±¡ã¯ã©ã¹ããã¤ã³ã¿ãã§ã¼ã¹ãé¸ã¶