如何在Kotlin中指定“自己的类型”作为返回类型
有没有办法指定函数的返回类型是被调用对象的类型?
例如
trait Foo { fun bar(): <??> /* what to put here? */ { return this } } class FooClassA : Foo { fun a() {} } class FooClassB : Foo { fun b() {} } // this is the desired effect: val a = FooClassA().bar() // should be of type FooClassA aa() // so this would work val b = FooClassB().bar() // should be of type FooClassB bb() // so this would work
实际上,这大致等于Objective-C中的instancetype
或Swift中的Self
。
没有任何语言功能支持这一点,但是您可以随时使用递归泛型(这是许多库使用的模式):
// Define a recursive generic parameter Me trait Foo<Me: Foo<Me>> { fun bar(): Me { // Here we have to cast, because the compiler does not know that Me is the same as this class return this as Me } } // In subclasses, pass itself to the superclass as an argument: class FooClassA : Foo<FooClassA> { fun a() {} } class FooClassB : Foo<FooClassB> { fun b() {} }
您可以使用扩展方法来实现“返回相同类型”效果。 下面是一个简单的例子,它显示了一个具有多个类型参数的基类型和一个扩展方法,该方法使用一个对所述类型的实例进行操作的函数:
public abstract class BuilderBase<A, B> {} public fun <B : BuilderBase<*, *>> B.doIt(): B { // Do something return this } public class MyBuilder : BuilderBase<Int,String>() {} public fun demo() { val b : MyBuilder = MyBuilder().doIt() }
由于扩展方法是静态解析的(至少从M12开始),如果需要特定于类型的行为,则可能需要让扩展委托实际实现。
你可以用扩展函数返回一些自己的类型。
interface ExampleInterface // Everything that implements ExampleInterface will have this method. fun <T : ExampleInterface> T.doSomething(): T { return this } class ClassA : ExampleInterface { fun classASpecificMethod() {} } class ClassB : ExampleInterface { fun classBSpecificMethod() {} } fun example() { // doSomething() returns ClassA! ClassA().doSomething().classASpecificMethod() // doSomething() returns ClassB! ClassB().doSomething().classBSpecificMethod() }