簡體   English   中英

Kotlin 在抽象類中調用伴隨對象

[英]Kotlin Calling Companion Object in Abstract Class

我有一個類Base是一個抽象類,定義為:

abstract class Base() {}

我想從這個基類創建一些派生類:

class A : Base() {}
class B : Base() {}
class C : Base() {}

我希望能夠調用一個通用函數create來執行一些初始化工作並返回指定的派生類(例如A )。 例如,類似以下的內容將是理想的:

val a = A.create() // `a` now holds an instance of `A`.
val b = B.create()
val c = C.create()

最初我嘗試在抽象類中使用伴隨對象作為一種靜態函數:

abstract class Base {
    companion object {
        fun create() : Base { 
            // Do some initialization and return the derived class
            // of the object. Obviously I can't return `Base` as I've
            // indicated above since it is an abstract class. This is
            // what I'm confused about: How do I return a copy of the
            // _derived_ class here? Is this impossible? I think it
            // might be...
            return Base() // <-- This doesn't work. What should be returned?
        }
    }
}

然后在派生類中:

class A : Base() {
    companion object {
        fun create() : A = Base.create()
    }
}

這行不通,原因很明顯。 即,我無法返回抽象類Base的實例。 有沒有一種簡單的方法來完成var a = A.create()范式? create的代碼在派生類中是相同的,所以我想避免在我創建的每個類中重新創建功能。

如果初始化邏輯相同並且基於Base類中指定的功能,您也可以這樣做:

abstract class Base() {

    protected fun init(): Base {
        // do the initialization
        return this
    }
}

class A : Base() {
    companion object {
        fun create() = A().init() as A
    }
}
abstract class Base {
    companion object {
        inline fun <reified T : Base> create() : T { 
            // you can use T::class here
        }
    }
}

class A : Base() {
    companion object {
        fun create() : A = Base.create() // inferred to Base.create<A>()
    }
}

可能工作,但可能需要使用不安全的反射。 這取決於您在create究竟想做什么......更好的做法是將類之間的任何不同作為函數傳遞,例如

abstract class Base {
    companion object {
        inline fun <reified T : Base> create(f: () -> T) : T { 
            val instance = f()
            // do something
            return instance // or something created from it
        }
    }
}

class A : Base() {
    companion object {
        fun create() : A = Base.create { A() }
    }
}

我假設您的類共享一個具有相同參數列表的構造函數。 然后你可以做的是定義一個特征

trait Instantiation[K] {

  def newWith(args):K
}

讓你的課程實現這個

class A implements Instantiation[A] {
  override def newWith(args):A
}

class B implements Instantiation[B] {
  override def newWith(args):B
}

class C implements Instantiation[C] {
  override def newWith(args):C
}

現在在共享邏輯中,您可以調用 newWith() 來返回正確的類型

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM