Я учусь на курсе Мартина Одерского по функциональному программированию в Scala, и сейчас я изучил две вещи, которые вместе не имеют смысла:
- Scala не поддерживает множественное наследование
Nothing
это подтип любого другого типа
Эти два утверждения не могут жить вместе, так как именно это делается? и что именно означает «подтип любого другого типа»
Редактировать 1
В API Scala , Nothing
определяется как abstract final class Nothing extends Any
... так как он может распространяться на другие классы?
programming-languages
scala
vainolo
источник
источник
Nothing
это подкласс любого другого класса. Это говорит о том, что это подтип любого другого типа .Ответы:
Подтип и наследование - это две разные вещи!
Nothing
не расширяет все, это подтип , он только расширяетсяAny
.Спецификация [§3.5.2] имеет особый случай , регулирующий подтипирования-отношения
Nothing
:Где в
<:
основном означает «это подтип».Что касается того, как это сделать: мы не знаем, это магия компилятора и детали реализации.
Довольно часто язык делает то, что вы, как программист, не можете. Как аналог
Nothing
: все в Scala наследуетсяAny
, все, кромеAny
. Почему неAny
наследует от чего-то? Вы не можете сделать это. Почему Scala может это сделать? Ну, потому что Скала устанавливает правила, а не ты.Nothing
Быть подтипом всего лишь другой пример этого.источник
null
что присваиваться полю любого типа в Java. Почему это возможно? Являетсяnull
ли экземпляр каждого класса? Нет, это возможно, потому что так говорит компилятор. Период.extends
в Java, а не композе Вы делаете это для подтипирования в конце концов.Когда он говорит, что Scala не поддерживает множественное наследование, он ссылается на наследование реализации метода несколько раз. Конечно, вы можете реализовать несколько интерфейсов / признаков в классе, и они могут даже определять один и тот же метод, но вы не получите конфликта между различными реализациями из-за линеаризации признаков.
В общем, если у вас есть класс
C1
с методомf()
и классC2
с методомf()
, то множественное наследование означает, что вы можете каким-то образом наследовать обе реализацииf()
. Это может привести к различным проблемам, которые Scala решает, позволяя вам наследовать только от одного класса, а в случае нескольких признаков - выбирать одну реализацию на основе порядка признаков.Что касается
Nothing
вещей действительно просто, потому что ничто не имеет никаких атрибутов или методов, определенных. Таким образом, вы не можете иметь никаких конфликтов наследования. Но я предполагаю, что большая часть вашего удивления исходит из другого понимания множественного наследования.Как только вы поймете, что линеаризация признаков эффективно устраняет любую двусмысленность наследования, и что мы не будем ссылаться на наследование от нескольких признаков как множественное наследование из-за этого, у вас все будет в порядке.
Что касается того, как это реализовано: компилятор в конечном итоге несет ответственность за это. См. Соответствие спецификации языка Scala в разделе 3.5.2, которое среди прочих свойств включает в себя:
Или, другими словами, если вы хотите правильно реализовать компилятор, он должен обрабатывать
Nothing
как подтип все по спецификации. По очевидным причинамNothing
не определено расширение из всех классов, загруженных в систему, но актуальность определения вNothing
качестве подтипа ограничена всеми местами, где подтип является релевантным.Важным моментом здесь является то, что не существует экземпляра типа
Nothing
, следовательно, его обработка строго ограничена проверкой типов, которая находится в области компилятора.источник