2012-10-18 22 views
9

Czy ktoś mógłby wyjaśnić, jak słowo kluczowe type i operator # działa w scala i jak z niego korzystać? Proszę spojrzeć na przykłady.badanie słów kluczowych "type" i "#" w scala

//Example1 
scala> type t1 = Option.type 
defined type alias t1 

//Shouldn't this work since previous example simply works? 
scala> type t2 = String.type 
<console>:7: error: type mismatch; 
found : String.type 
required: AnyRef 
     type t2 = String.type 
     ^

//lets define custom trait T 
scala> trait T 
defined trait T 

//... and obtain it's type like in Example1. 
//Shouldn't this work since previous Example1 simply works? 
scala> type t3 = T.type 
<console>:7: error: not found: value T 
     type t3 = T.type 
     ^

//Lets define some value of type T 
scala> val v4 = new T{} 
v4: T = [email protected] 

//and obtain it's type (works) 
scala> type t4 = v4.type 
defined type alias t4 

//this doesn't work 
scala> type t4_1 = (new T{}).type 
<console>:1: error: identifier expected but 'new' found. 
     type t4_1 = (new T{}).type 

//as well as this (doesn't work) 
scala> type t5 = "abc".type 
<console>:1: error: identifier expected but string literal found. 
     type t5 = "abc".type 
     ^

//but this compiles well 
scala> val v6 = "abc" 
v6: String = abc 

scala> type t6 = v6.type 
defined type alias t6 


//lets create some values of created types: 
scala> type t1 = Option.type 
defined type alias t1 

scala> val v1_1 = Some(10) 
v1_1: Some[Int] = Some(10) 

scala> type t7 = v1_1.type 
defined type alias t7 

scala> val v7:t7 = null 
v7: t7 = null 

scala> val v7_1:t7 = v1_1 
v7_1: t7 = Some(10) 

scala> val v7_2:t7 = Some(10) 
<console>:9: error: type mismatch; 
found : Some[Int] 
required: t7 
    (which expands to) v1_1.type 
     val v7_2:t7 = Some(10) 
      ^


//next let's try # operator 

scala> class X[A,B](a:A,b:B) 
defined class X 

//doesn't work 
scala> type xa = X[A,B]#A 
<console>:8: error: not found: type A 
     type xa = X[A,B]#A 
     ^
<console>:8: error: not found: type B 
     type xa = X[A,B]#A 
      ^

//but such approach works: 
scala> trait X2[C]{ 
    type A 
    type B 
    val c:C 
} 
defined trait X2 

scala> type xa2_1 = X2[String]#A 
defined type alias xa2_1 

scala> type xa2_2[M] = X2[M]#A 
defined type alias xa2_2 
+2

http://stackoverflow.com/a/6676210/298389 oraz http://stackoverflow.com/questions/10830308/class-alias-in-scala –

Odpowiedz

13

pierwszy, pytania o type:

Po prawej stronie deklaracji typu ma być nazwa typu ze stabilnej ścieżce. Więc biorąc swój jeden po drugim przykłady:

type t1 = Option.type 

t1 jest aliasem dla rodzaju Optionobiektu, a nie klasy Option. To jest błąd, ponieważ nie ma obiektu String. Błąd jest trochę dziwny, ponieważ String jest klasą Java i dlatego działa na innych zasadach (ponieważ klasy Java nigdy nie mają towarzyszy).

type t3 = T.type 

ditto. Tym razem błąd na jaśniejszy, ponieważ T jest klasa Scala i tak kompilator można jednoznacznie powiedzieć „T nie nazwać obiekt z typu”

type t4 = v4.type 

Jest to rodzaj Singleton obiektu nazwany przez val v4 . Nie odnosi się do żadnej instancji typu T ani nawet żadnej instancji anonimowej klasy utworzonej przez twoje wyrażenie new T{}. Odnosi się on do typu, który jest tylko reprezentowany przezi , tj. Są jedynymi dozwolonymi wartościami tego typu.

type t4_1 = (new T{}).type 

To jest nielegalne, ponieważ sprawa bierzesz rodzaju musi być stabilny identyfikator (z grubsza, identyfikator, którego referant może nigdy się nie zmieniają - jeśli pełna ścieżka do idenfier składa się tylko z nazwy pakietów, object s, i val s, jest stabilny).

type t5 = "abc".type 

Ditto.

type t6 = v6.type 

v6 jest stabilny identyfikator. t6 jest typem zamieszkałym wyłącznie przez to konkretne wystąpienie ciągu, które jest określane nazwą v6 (i null).

type v6 = v1_1.type 

Ponownie, typ singleton.

val v7: t7 = null 

null jest prawidłową wartością typu t7

val v7_1:t7 = v1_1 

Więc jest to konkretny przedmiot.

val v7_2:t7 = Some(10) 

Ale to inny obiekt (choć to == do v7, nie eq do niego), a zatem nie jest członkiem tego typu.

Teraz o #:

class X[A,B](a:A,b:B) 

A i B są parametry typu. Nie można ich przywoływać poza klasę. Można je traktować jak abstrakcyjne aliasy typu z widocznością private[this], ale to nie jest całkiem dokładne.

type xa = X[A,B]#A 

Tak, nie widać.

type xa2_1 = X2[String]#A 

Od toA odnosi się do typu alias publicznego, może być określany przez nazwę poza klasą. Zauważ, że ten konkretny przypadek jest całkiem bezużyteczny, ponieważ absolutnie nic nie wiesz o tym typie. jeśli cecha X2 miał metodę zwracanych wartości typu A, można zrobić coś jak

val aFromX2: xa2_1 = x2instance.methodThatReturnsAnA 

..ale to nie mógł nic innego z nim zrobić, a nawet przenieść go z powrotem do instancji X2[String] ponieważ nie ma gwarancji, że oba te numery będą się odnosić do tego samego typu! Z drugiej strony, jeśli masz konkretny przypadek, można to zrobić:

def passAroundA(x2instance: X2[String]) { 
    type x2a = x2instance.A // note dot, not # 
    val a: x2a = x2instance.methodThatReturnsAnA 
    x2instance.methodThatTakesAnA(a) 
} 

W tym przypadku to działa bo choć nie mamy pojęcia, co A rzeczywiście jest, wiemy, że dwie metody użyć ten sam typ - cokolwiek zostało ustalone w konstrukcji x2instance.

+0

Czy mógłbyś napisać więcej zdań na temat uzyskiwania dostępu do typu A za pomocą notacji kropkowej ? * wpisz x2a = x2instance.A // notka kropka, nie # * –

2

Praktycznie wszystko, co dotyczy Twojego pytania, zostało wyjaśnione w this imho absolutely essential talk na temat przypadków użycia, takich jak dopasowywanie wzorców itp. Proponuję poświęcić trochę czasu na obejrzenie go i wysiłek, aby się z tym pogodzić. Wiele rzeczy związanych z systemem scala Type było dla mnie magią, dopóki nie obejrzałem tego filmu. Mogłabym zaoszczędzić wielu moich ludzi próbując rozwiązać dziwne zachowanie systemu typów i wnioskowania o typ, jeśli wiedziałem o tych rzeczach.

Powiązane problemy