Что такое класс actall для определения синтаксиса структурного типа? - PullRequest
5 голосов
/ 31 августа 2011

Пример:

type T = MyClass {def someMethod:String} 

Означает ли это, что компилятор создает черту типа "trait AnonTrait extends MyClass {def someMethod:String}"?Или это делается через другой механизм компилятора?Мой вопрос был о том, что на самом деле скрыто этим синтаксисом Type.

Ответы [ 3 ]

3 голосов
/ 31 августа 2011

Это не скрывает создание типа.В основном он маскирует использование отражения для проверки ваших структурных ограничений во время компиляции и для вызова someMethod во время выполнения.

Например, если у вас есть:

class Foo(t: MyClass {def someMethod:String}) {
    def CallSomeMethod = t.someMethod
}

, это означает конструктор для вашего Fooкласс принимает в типе MyClass, который также имеет someMethod (где someMethod может быть смешан с MyClass через черту).Вы можете иметь:

class MyClass {}
trait WithSomeMethod {def someMethod = "hello"}  

и затем вы можете создать Foo следующим образом:

val mc = new MyClass with WithSomeMethod
val foo = new Foo(mc)
println(foo.CallSomeMethod) // prints "hello"

сейчас, когда вы создаете new Foo(mc), компилятор использует отражение, чтобы проверить, что mc является MyClassу этого также есть некоторый метод.Фактический вызов foo.CallSomeMethod также работает через отражение.

Теперь (потерпите меня, я перехожу к вашему актуальному вопросу ...), действуя так, как вы:

type T = MyClass {def someMethod:String} 

создает только псевдоним типа, а не конкретный тип.Как только вы определили T таким образом, вы можете определить Foo как:

class Foo(t: T) {
    def CallSomeMethod = t.someMethod
}

, что эквивалентно определению Foo, данному ранее.Вы только что создали псевдоним T, который можно использовать в других местах, где вы могли использовать MyClass {def someMethod:String}.Фактический тип T не генерируется, и компилятор по-прежнему использует отражение всякий раз, когда вы ссылаетесь на T, чтобы проверить структурное ограничение, определившее someMethod, и по-прежнему генерирует код на основе отражения, чтобы вызвать someMethod.

3 голосов
/ 31 августа 2011

Учтите это: у класса нет структурного типа. Тип класса всегда является классом. Черта создает интерфейс. Тип объекта-одиночки также является классом.

А где появляются структурные типы? как типы параметров и переменных.

Например, я могу сказать def f(s: { def size: Int }) или val r: { def close(): Unit }.

Теперь, как эти типы отображаются как байт-код? Как и любой другой тип, не поддерживаемый JVM (например, собственные дженерики Java), они стерты .

Итак, что касается всех остальных (т. Е. Не Scala), типы s и r выше java.lang.Object.

Для самой Scala некоторая дополнительная информация хранится в аннотации, которая дает точную информацию об этих типах в том виде, в котором их понимает Scala.

3 голосов
/ 31 августа 2011

Он не создает черту, это только псевдоним типа, который означает, что каждый раз, когда вы ссылаетесь на T, вы фактически ссылаетесь на MyClass {def someMethod:String}.Однако вы можете переопределить объявление типа с помощью черты:

trait A

class B {
  type T <: A
}

class SubB {
  trait T extends A
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...