2011-07-29 11 views
6

Poszukuję sposobu zdefiniowania metody zwracającej typ T, gdzie T = typ podklasy.Scala typ abstrakcyjny reprezentujący typ podklasy

Wiem, że mógłbym to zrobić za pomocą typów abstrakcyjnych, ale nie podoba mi się konieczność redefiniowania T dla każdej podklasy.

Niektóre przykładowy kod:

object Helper { 
    def help[A <: MyClass](cls: A): Option[A] = { cls.foo() map { _.asInstanceOf[A] } } 
} 

class MyClass { 
    type T <: MyClass 
    def foo(): Option[T] = Some(this.asInstanceOf[T]) 
} 

class ChildClass extends MyClass { 
    type T = ChildClass 
} 

Prawdopodobnie nowa funkcja język dokonał tego łatwiej? A może w jakiś sposób mogę użyć this.type? To dla mnie ważne, że mogę zdefiniować klasę pomocników, która może w ten sposób wywoływać foo.

Odpowiedz

3

Jeśli zawsze wracasz this, możesz rzeczywiście mieć jako typ zwrotu this.type. A może już to wypróbowałeś?

this.type jest szczególnie przydatny, np. kiedy chcesz połączyć się z łańcuchem do tego samego obiektu lub dostarczyć statyczną gwarancję, że zwrócisz ten sam obiekt (a nie kopię). Na przykład: Buffer s w Scali mają operację dołączenia :+, która zwraca Buffer[A] i +=, która zwraca this.type. Ten pierwszy duplikuje zmienną sekwencję; ten ostatni gwarantuje aktualizację oryginalnego obiektu.

+1

jakaś szansa możesz wskazać mi jakąś specyficzną składnię, która działałaby, biorąc pod uwagę, że muszę napisać Helper.help dokładnie tak, jak jest (z parametrem typu)? this.type nie pasuje do A? Zwróć też uwagę, że muszę zwrócić Option [this.type] i def foo: Option [this.type] = Niektóre (to) nie wydają się kompilować. Dzięki za pomoc! –

+1

@Pandora Singleton typy nigdy nie są wnioskowane, musisz określić to jawnie: 'Some [this.type] (this)'. –

+0

Dziękuję bardzo! Natknąłem się na inną usterkę, ponieważ moja funkcja foo faktycznie wywołuje metodę statyczną innego obiektu -> kontynuuj pytanie tutaj, jeśli masz spostrzeżenia :) http://stackoverflow.com/questions/6886182/scala-this- zgodność typu z typem - granice supertekstu –

2

Aby śledzić na odpowiedź Jean-Phillippe użytkownika, który napisał swoją dokładnie kiedy piszę moje, oto kod:

trait SomeTrait { 
    def foo: this.type = this 
} 

class UsesTrait extends SomeTrait 

object Main { 
    def main(args: Array[String]) { 
    println((new UsesTrait).foo) // prints [email protected]<hash value> 
    } 
} 
+0

Fajnie, to jest pomocne. Czy to rozszerza się na Option [this.type]? def foo: Option [this.type] = Niektóre (to) nie wydają się kompilować. –

+0

Heh, w końcu też to zrobiłem. Jest to jedna z najbardziej niedostatecznie udokumentowanych funkcji językowych, biorąc pod uwagę, jak ważna jest ... – lisak

2

znalazłem następujące idiom przydatne:

class MyClass[T] { 
    self: T => 
    def foo(): Option[T] = Some(this) 
} 

class ChildClass extends MyClass[ChildClass] 

new ChildClass().foo() 
//--> Option[ChildClass] = Some([email protected]) 
+0

Tak, ale: • musi to być cecha, jeśli chcesz pozwolić na całą hierarchię klas, oraz • musi być kowariantna w ' T'. Ogólnie rzecz biorąc, więcej ograniczeń niż prosty "ten.type", nie? –

+0

@ Jean-Philippe Pellet: Tak, wygląda. Rozmyślam, czy to też może mieć zalety, ale go nie znalazłem. – Landei