2013-09-11 2 views
3

Это довольно сложно изучить общие рамки Scala. Я знаю, что:Общие рамки, большинство из них неясны

T : Tr - T имеет тип Tr, то есть он реализует чертаTr

T <: SuperClass - T является подкласс SuperClass

T :> ChildClass - T является суперкласс ChildClass

Однако есть еще много операторов:

<% и %>

=:= 

<:< и >:>

<% и %>

<%< и >%>

Я читал о них, но, как я уже сказал, не было внятные объяснения , Не могли бы вы прояснить ситуацию?

+0

есть хорошее объяснение на виде и контекст оценку на сайте http://docs.scala-lang.org/tutorials/FAQ/context лестницы и-вид-bounds.html –

ответ

3

Я использовал несколько ограничений типа:

  1. Простейшим являются <: и >:. Это простые оценки иерархии типов.

    trait A 
    trait B extends A 
    trait C extends B 
    

    то для метода

    def doSomething[T >:C <:B](data:T) 
    

    либо B или C может быть замещен вместо T

  2. Затем введите ограничения, которые включают в себя добавление неявного параметра к методу.

    def doSmth1[T: MyTypeInfo] (data:T) 
    

    переписывается во время компиляции, как

    def doSmth1[T] (data:T)(implicit ev: MyTypeInfo[T]) 
    

    тогда

    def doSmth2[T <% SomeArbitratyType] (data:T) 
    

    переписывается в виде

    def doSmth2[T] (data:T)(implicit ev: T => SomeArbitratyType) 
    

    Оба методов можно назвать, если в объеме существует экземпляр, который соответствует неявный параметр. Если нет соответствующего экземпляра, компилятор выдает ошибку.

    Ссылка на просмотр (<%) требует неявного преобразования, которое преобразует T в экземпляр другого типа (SomeArbitratyType).

    Более мощный использует «классы типов». Внутри экземпляра класса типа можно указать множество полезных методов, которые могут иметь дело с типом T. В частности, можно применить метод преобразования и получить аналогичный результат в виде границ представления.

    Примеры:

    trait MyTypeInfo[T] { 
        def convertToString(data:T):String 
    } 
    def printlnAdv[T : MyTypeInfo](data:T) { 
        val ev = implicitly[MyTypeInfo[T]] 
        println(ev.convertToString(data)) 
    } 
    

    где-то в объеме должны быть неявным значением типа MyTypeInfo[T]:

    implicit val doubleInfo = new MyTypeInfo[Double] { 
        def convertToString(data:Double):String = data.toString 
    } 
    

    или

    implicit def convertToString(data:T):String 
    
    def printlnAdv[T <% String](data:T) { 
        val conversionResult = data : String 
        println(conversionResult) 
    } 
    

    где-то в объеме должен быть неявной функцией :

    implicit def convertDoubleToString(data:Double):String = data.toString 
    
  3. Следующие странные символы: =:= и <:<. Они используются в методах, которые хотят гарантировать, что тип имеет некоторое свойство. Конечно, если вы объявите общий параметр, то достаточно указать <: и >:, чтобы указать тип. Однако что делать с типами, которые не являются общими параметрами? Например, общий параметр охватывающего класса или некоторый тип, который определен в другом типе. Символы здесь помогают.

    trait MyAlmostUniversalTrait[T] { 
        def mySpecialMethodJustForInts(data:T)(implicit ev:T =:= Int) 
    } 
    

    Характеристика может использоваться для любых типов T. Но метод можно вызвать только в том случае, если этот признак создается для Int.

    Подобный прецедент существует для <:<. Но здесь мы не имеем «равных» ограничений, но «меньше» (например, T<: T2).

    trait MyAlmostUniversalTrait[T] { 
        def mySpecialMethod(data:T)(implicit ev:T <:< MyParentWithInterestingMethods) 
    } 
    

    Опять метод может только можно назвать для типов, которые являются потомками MyParentWithInterestingMethods.

  4. Тогда <%< очень похож на <%, однако она используется так же, как <:< - как неявный параметр, если тип не является универсальным параметром. Это дает преобразование в T2:

    trait MyAlmostUniversalTrait[T] { 
        def mySpecialMethod(data:T)(implicit ev:T <%< String) { 
        val s = data:String 
        ... 
        } 
    } 
    

    ИМХО <%< можно спокойно игнорировать. И один может просто объявить требуемую функцию преобразования:

    trait MyAlmostUniversalTrait[T] { 
        def mySpecialMethod(data:T)(implicit ev:T => String) { 
        val s = data:String 
        ... 
        } 
    } 
    
Смежные вопросы