Как указать «собственный тип» в качестве возвращаемого типа в Котлине

Есть ли способ указать тип возврата функции как тип вызываемого объекта?

например

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 

По сути, это будет примерно эквивалентно instancetype в Objective-C или Self в Swift.

Не существует языковой функции, поддерживающей это, но вы всегда можете использовать рекурсивные дженерики (который является шаблоном, которым пользуются многие библиотеки):

 // 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), вам может потребоваться, чтобы делегат расширения выполнял фактическую реализацию до this если вам нужно поведение по типу.

Вы можете вернуть что-то собственное, используя функции расширения .

 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() } 
Intereting Posts
Kotlin: Сравнить значения свойств различных целевых объектов с (out) отражением Получить идентификатор ресурса android из строки Делегация класса Kotlin Mvp для Android Функции расширения Котлина внезапно требуют уровня api 24 android studio 3.0.1 и kotlin v1.2.10-release-Studio3.0-1 получили проблемы jvm сравнение String с StringBuffer.reverse () всегда не выполняется Как установить функцию прослушивания кликов и передать значение поля edittext для просмотра модели с использованием привязки данных В чем разница между нормальным классом и классом данных в котлине Как заполнить доступную ширину таблицы с столбцами? Recruit-MP LightCalendarView – ошибка раздувания класса, noSuchMethodException Kotlin Pass в типе, который реализует параметризованный интерфейс Android Studio демонстрирует предупреждение зависимостей Kotlin после второй сборки Вывод типа Kotlin не выполнен Как вручную подключить Kotlin fun с помощью <reified T: Any> Слушатель не вызывается, когда запрашивается диалоговое окно «Обновление сервисов Google Play»