Kotlin: Как я могу создать «статическую» наследуемую функцию?

Например, я хочу иметь example() функции example() для типа Child который расширяет Parent чтобы я мог использовать функцию для обоих.

 Child.example() Parent.example() 

Первый «очевидный» способ сделать это – через сопутствующий объект Parent , но это не позволяет example() для Child .

Второй способ, которым я пытался, – определить функцию расширения на Parent.Companion , что неудобно, потому что вы вынуждены определять объект-компаньон. Это также не позволяет example() для Child .

Кто-нибудь знает, как я могу это сделать?

То, о чем вы просите, не существует, вы, кажется, спрашиваете:

Могу ли я ссылаться на метод сопутствующих объектов суперкласса из ссылки класса его потомков

или, может быть, вы спрашиваете:

Могу ли я ссылаться на статический член суперкласса из ссылки его потомков.

Ответ для обоих – нет . По замыслу Котлина, что это запрещено, было сознательным решением, было преднамеренным. Если вы хотите изменить это решение, вам нужно будет указать проблему в YouTrack . Программисты на Java были в большой степени запутаны наследованием и переопределением статических методов и поведения при вызове из одной ссылки по сравнению с другой и как она статически разрешена, а не динамически. Команда Java 8 при добавлении статических методов в интерфейсы реализует путаницу, которая может привести к этому, поэтому они приняли более подход Kotlin, только позволяя ему вызываться по ссылке интерфейса. Чтобы избежать этих кошмаров, команда Котлина не разрешала это. Так же, как они запретили многие другие запутывающие аспекты Java.

Другие ответы (например, @ voddan) дают вам обход, чтобы иметь такое же ощущение синтаксиса вызова с помощью сопутствующих объектов, но вы отклоняете их в своих комментариях, говоря, что хотите избежать сопутствующего объекта, даже если в вашем вопросе говорится, что вы пытаются их использовать. Поэтому, полагая, что вы не хотите их использовать, ответ просто нет, не может быть сделано .

Чтобы избавиться от объекта-компаньона, вы хотели бы поговорить о возможностях расширения Can в статическом режиме? … который будет разочаровывающим, поскольку он еще не разрешен.

Возвращаясь к сопутствующим объектам (извините, но они – единственный путь к славе здесь), вы можете просто вручную делегировать метод дочернего элемента родительскому:

 open class Parent { companion object { // required, sorry, no way around it! fun foo() = /* some cool logic here */ } } class Child: Parent() { companion object { // required, sorry, no way around it! fun foo() = Parent.foo() } } 

Или как расширения:

 open class Parent { companion object {} // required, sorry, no way around it! } class Child: Parent() { companion object {} // required, sorry, no way around it! } fun Parent.Companion.foo() = /* some cool logic here */ fun Child.Companion.foo() = Parent.foo() 

Поскольку сопутствующие объекты играют по тем же правилам, что и любые другие, легко использовать обычные средства повторного использования кода на них:

 open class Example { fun example() {} } class Parent { companion object : Example() } class Child { companion object : Example() } fun main(args: Array<String>) { Child.example() Parent.example() } 

В качестве альтернативы, с помощью делегирования класса вы можете напрямую использовать реализацию из Parent :

 interface Example { fun example() } class Parent { companion object : Example { override fun example() {} } } class Child { companion object : Example by Parent.Companion } 

Целью является создание «альтернативного оператора» для строительства

В Java вы должны использовать Factory вместо статического метода при использовании в качестве «конструктора».

На стороне Котлина вы можете использовать функцию верхнего уровня вместо Factory.

Или, если вы действительно хотите иметь «статический метод» в своем классе, я бы создал объект-компаньон и добавлял статические методы расширения.