简体   繁体   English

Kotlin 在抽象类中调用伴随对象

[英]Kotlin Calling Companion Object in Abstract Class

I have a class, Base that is an abstract class and is defined as:我有一个类Base是一个抽象类,定义为:

abstract class Base() {}

I'd like to create a handful of derived classes from this base class:我想从这个基类创建一些派生类:

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

I would like to be able to call a common function create that does some initialization work and returns the specified derived class (eg A ).我希望能够调用一个通用函数create来执行一些初始化工作并返回指定的派生类(例如A )。 For example, something like the following would be ideal:例如,类似以下的内容将是理想的:

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

Initially I tried to use a companion object in the abstract class as a sort of static funcion:最初我尝试在抽象类中使用伴随对象作为一种静态函数:

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?
        }
    }
}

Then in the derived class:然后在派生类中:

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

This doesn't work, for obvious reasons.这行不通,原因很明显。 Namely, I can't return an instance of the abstract class Base .即,我无法返回抽象类Base的实例。 Is there an easy way to accomplish the var a = A.create() paradigm?有没有一种简单的方法来完成var a = A.create()范式? The code for create will be identical across derived classes, so I wanted to avoid having to recreate the functionality in each class I create. create的代码在派生类中是相同的,所以我想避免在我创建的每个类中重新创建功能。

If the initialization logic is the same and is based on the functionality specified in the Base class you can also do it like this:如果初始化逻辑相同并且基于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>()
    }
}

may work but probably need to use unsafe reflection.可能工作,但可能需要使用不安全的反射。 It depends on what exactly you want to do in create ... A better practice would be to pass whatever is different between the classes as a function, eg这取决于您在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() }
    }
}

I am assuming your classes share a constructor with the same argument list.我假设您的类共享一个具有相同参数列表的构造函数。 What you then can do is define a trait然后你可以做的是定义一个特征

trait Instantiation[K] {

  def newWith(args):K
}

have your classes implement this让你的课程实现这个

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
}

and now in the shared logic you can call newWith() to return the correct type现在在共享逻辑中,您可以调用 newWith() 来返回正确的类型

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM