2016-09-03 16 views
10

Na przykład chcę mieć funkcję example() na typie Child, która rozciąga się na Parent, dzięki czemu mogę korzystać z funkcji na obu.Kotlin: Jak utworzyć "statyczną" dziedziczną funkcję?

Child.example() 
Parent.example() 

Pierwszy „oczywisty” sposób to zrobić za pośrednictwem obiektu towarzysz Parent, ale to nie zezwala example() dla Child.

Drugi sposób, który próbowałem, to zdefiniowanie funkcji rozszerzenia na Parent.Companion, co jest niewygodne, ponieważ jesteś zmuszony zdefiniować obiekt towarzyszący. Nie zezwala również na example() dla Child.

Czy ktoś wie, jak mogę to zrobić?

+0

Do czego służy funkcja dziedziczenia statycznego ??? –

+0

@DanielTran Cóż, niekoniecznie jest "statyczne", ponieważ jest to Kotlin. Celem jest stworzenie "alternatywnego operatora" do budowy, np. 'Dziecko [1, 2, 3]' zamiast 'Dziecko (1, 2, 3)' – Jire

+0

@DanielTran Co powiesz na przykład na egzekwowanie metod fabrycznych dla klas potomnych? – IARI

Odpowiedz

11

co prosicie, nie istnieje, to wydaje się być pytanie:

Mogę odwołać metodę obiektu towarzysz nadklasie z odniesieniem klasowej jego potomków

lub może pytasz:

Czy mogę odwołać się do statycznego członka nadklasy z referencji jego potomków.

Odpowiedź dla obu jest nr. Jest według projektu z Kotlin, że jest to niedozwolone, było świadomą decyzją, było celowe. Jeśli chcesz zmienić tę decyzję, musisz file an issue in YouTrack. Programiści w języku Java byli mocno zdezorientowani przez dziedziczenie i nadpisywanie metod statycznych i zachowanie, gdy są wywoływane z jednego odniesienia w stosunku do drugiego i sposób jest statycznie rozwiązany, a nie dynamicznie. Zespół Javy 8 przy dodawaniu statycznych metod do interfejsów zdaje sobie sprawę z zamieszania, jakie mogłoby to spowodować, więc przyjęli oni więcej niż tylko metody Kotlin, pozwalając na wywoływanie ich przez odniesienie do interfejsu. Aby uniknąć tego rodzaju koszmarów, zespół Kotlin go odrzucił. Tak jak nie dopuszczali wielu innych mylących aspektów Javy.

Inne odpowiedzi (na przykład @ voddan) dają możliwość obejścia, aby wywoływać taką samą składnię, używając companion objects, ale odrzucasz te komentarze, mówiąc, że chcesz uniknąć obiektu towarzyszącego, nawet jeśli pyta stany, których próbujesz użyć. Zakładając, że nie chcesz ich używać, odpowiedź brzmi po prostu nie, nie można tego zrobić.

Aby pozbyć się obiektu towarzyszącego, chciałbyś porozmawiać o Can extension functions be called in a “static” way? ... co będzie rozczarowujące, ponieważ nie jest jeszcze dozwolone.

Wracając do obiektów towarzyszących (przepraszam, ale to jedna droga do chwały tutaj), można też po prostu ręcznie delegować metodę dziecka do rodzica:

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() 
    } 
} 

lub jako rozszerzenia:

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() 
7

Od towarzysz obiektów grać według tych samych zasad jak każde inne, jest łatwy w użyciu normalnych sposobów ponownego użycia kodu na nich:

open class Example { 
    fun example() {} 
} 

class Parent { 
    companion object : Example() 
} 

class Child { 
    companion object : Example() 
} 

fun main(args: Array<String>) { 
    Child.example() 
    Parent.example() 
} 

Alternatywnie klasie delegacji można ponownie realizację od Parent bezpośrednio:

interface Example { 
    fun example() 
} 

class Parent { 
    companion object : Example { 
     override fun example() {} 
    } 
} 

class Child { 
    companion object : Example by Parent.Companion 
} 
+0

Czy istnieje jakiś sposób obejścia konieczności zdefiniowania obiektu towarzyszącego? – Jire

+0

Może to być zwykły obiekt;) – voddan

0

Celem jest stworzenie „alternatywnego operatora” budowy

W języku Java należy użyć fabryki zamiast metody statycznej, gdy jest używana jako "konstruktor".

Po stronie Kotlin można użyć funkcji najwyższego poziomu zamiast fabryki.

Jeśli naprawdę chcesz mieć "klasę statyczną" w swojej klasie, , utworzę obiekt towarzyszący i dodaję metody statycznych rozszerzeń.

+0

Wszystko, co wspomniano, jest słuszne, ale lekcje dla dzieci nie mogą z nich korzystać. – Jire

+0

Czy przegapiłeś import funkcji rozszerzenia? Statyczne funkcje rozszerzenia powinny być dostępne w pod-klasach po ich zaimportowaniu. – D3xter

+0

Przepraszam, powinienem był napisać o tym lepiej. Chodzi mi o to, że nie możesz ich używać automatycznie na lekcje dla dzieci. Podobnie jak przy definiowaniu funkcji 'przyklad()' w obiekcie towarzyszącym obiektu nadrzędnego o nazwie 'Rodzic', można wykonać' Parent.example() '; z dzieckiem obiektu 'Parent' nazwanego' Child', nie można automatycznie wykonać funkcji 'Child.example()'. – Jire