Интересно, если я использую Un Seal trait
или abstract class
Scala, а затем использую сопоставление с образцом, не знает ли компилятор во время компиляции для этого конкретного образца, какие возможные реализации этой черты / класса доступны? Так что, если это так, может ли он не выдавать предупреждения о совпадении с образцом, даже если trait
/ abstract class
не запечатан, потому что он знает, какие типы могут использоваться, проверяя все возможные зависимости / импорт?
Например, если у меня есть Option[A]
и я сопоставляю шаблоны только для, Some[A]
но не для None
, компилятор будет жаловаться, потому что Option
запечатан.
Если компилятор не может знать / решить это, то почему он не может? И если компилятор (теоретически) может это сделать, то каковы причины того, что он не используется в Scala? Существуют ли другие языки, поддерживающие такое поведение?
источник
Foo
с подклассамиA
,B
иC
, и все ваши сопоставления с образцом соответствуют только этим трем. Ничто не мешает мне добавить новый подкласс,D
который взорвет ваши соответствия шаблону.java.lang.ClassLoader
.Ответы:
Выяснение всех подклассов класса называется анализом иерархии классов, и выполнение статического CHA на языке с динамической загрузкой кода эквивалентно решению проблемы остановки.
Кроме того, одной из целей Scala является отдельная компиляция и развертывание независимых модулей, поэтому компилятор просто не может знать, является ли класс подклассами в другом модуле, потому что он никогда не рассматривает более одного модуля. (В конце концов, вы можете скомпилировать модуль с интерфейсом какого-либо другого модуля, даже если этот модуль не существует в вашей системе!). Поэтому
sealed
необходимо, чтобы все подклассы были определены в одном модуле компиляции.Это также одна из причин того, почему JVM могут так выгодно конкурировать с компиляторами C ++: компиляторы C ++ обычно являются статическими компиляторами, поэтому они не могут вообще выяснить, является ли метод переопределенным или нет, и, следовательно, не могут встроить его. JVM OTOH, как правило, являются динамическими компиляторами, им не нужно выполнять CHA, чтобы выяснить, переопределен ли метод или нет, они могут просто посмотреть на иерархию классов во время выполнения. И даже если на более позднем этапе выполнения программы появится новый подкласс, которого раньше не было, ничего страшного, просто перекомпилируйте этот кусок кода без вставки.
Примечание: все это относится только к Scala. JVM не имеет понятия о
sealed
, так что вполне возможно создать подклассыsealed
классов из другого языка JVM, поскольку нет способа передать это на другой язык.sealed
Свойство записывается вScalaSig
аннотации, но компиляторы других Языков не принимать эти аннотаций во внимание, очевидно.источник
Это можно сделать (по крайней мере, для всех классов, известных во время компиляции), это просто дорого. Вы полностью уничтожите пошаговую компиляцию, потому что все, что содержит сопоставление с образцом, будет эффективно перекомпилироваться каждый раз при изменении любого другого файла.
А что ты покупаешь? Запах кода заключается в написании совпадений с образцами, которые необходимо часто менять при добавлении нового производного класса. Это нарушение принципа открытого / закрытого . Правильно используйте наследование, и вам не нужно будет писать подобные совпадения. И да, принцип открытия / закрытия также применим к функциональным языкам без наследования на основе классов. Фактически, между такими функциями, как классы типов, мультиметоды и просто обычные функции высшего порядка, функциональные языки значительно упрощают расширение без изменений.
источник
It can be done (at least for all classes known at compile time), it's just expensive.
Но если программа не на 100% автономна (то есть зависит от внешних.jar
файлов), не могли бы вы пробраться в новый подкласс после компиляции через один изjar
s? Таким образом, компилятор может сказать вам: «Ваши сопоставления с образцами сейчас исчерпывающие, но это может измениться, если какая-либо из ваших зависимостей изменится», что довольно бесполезно, поскольку смысл наличия внешних зависимостей состоит в возможности их обновления без перекомпиляции!