Какие существуют причины для различий между типами времени компиляции и типами времени выполнения? - PullRequest
5 голосов
/ 26 января 2011

В Scala / Java (~ в JVM) есть несколько небольших случаев, когда поведение отличается, например:

/* "Dynamic" cast */
"".getClass.cast("Foo")
//res0: Any = Foo

/* "Static" cast */
classOf[String].cast("Foo")
//res1: String = Foo

/* "Compile time cast" */
"Foo".asInstanceOf[String]
res2: String = Foo

В каких языках разрыв между временем компиляции и временем выполнения больше иЕсть ли причины из POV дизайна языка, почему это могло бы быть «хорошо»?

Переход в другое направление: существует ли (статически типизированный) язык без каких-либо различий между временем компиляции итипы времени выполнения?

Ответы [ 2 ]

6 голосов
/ 26 января 2011

Причина первого результата в том, что метод getClass имеет следующую подпись в Java

public final Class<?> getClass()

который наследует Скала. Хотя мы знаем, что если мы вызовем getClass для ссылки типа T, подпись может быть

public final Class<? extends T> getClass()

компилятор не делает. Вы могли бы представить какое-то расширение языка для предоставления специального типа, представляющего статический тип получателя, который позволил бы

public final Class<? extends Receiver> getClass()

или какой-то специальный регистр в компиляторе для getClass. На самом деле кажется, что Snoracle Java действительно особый случай getClass, но я не уверен, что это требуется спецификацией языка Java. Однако, если у вас есть ссылка на какой-то конкретный статический тип T, нет никаких причин, по которым вы не можете сделать эквивалент T.class (java) или classOf[T] (scala). Другими словами, такое расширение не принесло бы большей выразительной силы, но усложнило бы реализацию языка.

Что касается «приведения времени компиляции» и «статического» приведения, то здесь действительно нет никакой разницы. Было бы правильно, чтобы компилятор десугар x.asInstanceOf[T] до classOf[T].cast(x).

Любой язык с подтипами будет иметь возможность того, что статически известный тип ссылки менее специфичен, чем тип значения, к которому он относится. Языки со статическими системами типов, которые не имеют подтипов, обычно не имеют понятия о типах времени выполнения, поскольку существует только один фактический тип, который населяет данное имя типа. В этих языках типы стираются во время выполнения, почти так же, как параметры типа стираются в JVM.

Надеюсь, это поможет вам понять статические типы ссылок по сравнению с типом значений во время выполнения.

1 голос
/ 28 января 2011

C не имеет информации типа времени выполнения (RTTI). Таким образом, статический тип является типом времени выполнения. Точнее, это позволяет компилятору полностью исключить информацию о типе из объектного файла и генерировать более быстрый код (проверка во время выполнения программы не требуется). Для связи информация есть в заголовках.

В C ++ RTTI существует только с виртуальным наследованием / абстрактными базовыми классами, что является обескураживающей идиомой из-за плохой производительности (по стандартам C ++).

В Java (насколько я помню) предпочтительной идиомой (по крайней мере 7 лет назад) было использование очень общего интерфейса. Это означает, что не так много информации о типе времени компиляции. И, конечно, дженерики в Java имеют все объекты в качестве статического типа. Таким образом, вся информация является временем выполнения (с соответствующими издержками). Причиной этого, по-видимому, является то, что статические системы типов либо слишком жесткие (C, Pascal) и требуют лазеек (void *), либо относительно сложные (C ++, Haskell).

В Haskell типом компиляции обычно является тип времени выполнения, кроме случая типов более высокого порядка и экзистенциального типа. GHC по какой-то причине (отражение? Создание экземпляра класса?), Однако, не использует это для повышения эффективности. Таким образом, информация о типе - все runtme.

...