2012-02-27 6 views
3

Синтаксис scala очень перспективен. Я думал, что первоначально scala - это больше, чем просто удобная Java и может ввести совершенно новую парадигму программирования, но многие функции, разрешенные синтаксисом, неверны в семантике. Поэтому я начал поиски поиска ограничений scala и хаки, чтобы их устранить. Хотя я просто пишу тестовый проект, чтобы приспособиться к способам и шаблонам scala с другой точки зрения.Когда происходит стирание типа типа?

Главным препятствием является стирание типа, унаследованное от реализации jvm. Я могу написать небольшую статью под названием «Десять красивых узоров, которые стирают стирание». Говорят, что стирание стирает дженерики, но я наткнулся на стирание стилей в mixins. Я рассматриваю проблему с реализацией mixin в scala.

Преамбула

trait T1 
trait T2 

trait B1 { 
    def typeMe(x:T1){} 
} 

Разбитый Код с Mixins

trait B2 extends B1 { 
    def typeMe(x:T1 with T2) {} 
} 

рабочего кода с Mixin объявлен как отдельный признак

trait T3 extends T1 with T2 
trait B3 extends B1 { 
    def typeMe(x:T3) {} 
} 

Ошибка:

error: name clash between defined and inherited member: 
method typeMe:(x: T1 with T2)Unit and 
method typeMe:(x: T1)Unit in trait B1 
have same type after erasure: (x: $line12.$read#$iw#$iw#T1)Unit 
    def typeMe(x:T1 with T2) 

Какое лучшее обходное решение доступно? Представление нового признака - это словосочетание (особенно для больших цепей mixin) и приводит к несовместимости типов. Добавление ложных неявных аргументов также не является серебряной пулей, потому что это увеличивает накладные расходы.


обновление:

Мне очень жаль, я задал неправильный вопрос. Мне больше интересна природа описанной ошибки, а не ее обходные пути. Где происходит стирание типа? Я не вижу дженериков в коде, который считается типом источника стирания. Какова механика поведения компилятора?

+1

Вы можете рассмотреть альтернативу перегруженным методам; назовите их по-разному или используйте шаблон typeclass. – Owen

+4

Надеюсь, вы понимаете, что в 'B3' вы не переопределяете метод' typeMe' из 'B1', но перегружаете его, чтобы взять подтип. Хотя это законно, это плохая идея, так как вызванный метод будет зависеть от типа локальной переменной. т. е. при условии, что объект 'B3'' b3' и объект 'T3'' t3', 'b3.typeMe (t3)' и 'b3.typeMe (t3: T1)' будут вызывать разные методы. –

ответ

3

Есть пара проблем с тем, что вы пытаетесь сделать.

Во-первых, это не имеет значения, когда происходит стирание типа. Это связано с тем, что концепция стирания типов заключается в том, что стирать типы до или после вычисления, результат должен быть одинаковым. Для языков JVM некоторое стирание происходит во время компиляции, iinm.

Во-вторых, ваш «рабочий» код на самом деле не работает так, как вы думаете. Это требует небольшого понимания о подтипировании, ковариации и контравариантности. (Foo <: Bar означает, что «Foo является подтипом Bar», или неофициально, что «Foo более конкретный, чем Bar»). Функции контравариантны в их вводе и ковариантны в их выходе, что означает, что функция A => B <: W => V только если W <: A и B <: V.

Теперь рассмотрим ваши функции:

B1.typeMe(x:T1) 
B3.typeMe(x:T3) 

Входной сигнал B3.typeMe является T3, в то время как тип входа в B1.typeMe является T1. Однако T3 <: T1 (T3 более конкретно, чем T1), поэтому тип B3.typeMeне может быть подтипом типа B1.typeMe. Вместо этого они просто считаются отдельными функциями, причем иногда случается какое-то жуткое молчание.Честно говоря, это должно, вероятно, исправить ошибку или хотя бы предупреждение. К счастью, другая версия.

+0

Я не написал на самом деле вопрос. Главный вопрос заключался в том, где происходит стирание типа, какие дженерики стоят за ошибкой. – ayvango

Смежные вопросы