2010-08-06 3 views
9

Скажет, у меня есть следующие черты:типа Самого наследования в Скале

trait A 

trait B { this: A => } 

trait C extends B // { this: A => } 

Compiler ошибка: illegal inheritance; self-type C does not conform to B's selftype B with A
Как и следовало ожидать, если я раскомментировать самостоятельно аннотацию типа, компилятор доволен.

Я думаю, что совершенно очевидно, почему C тоже нуждается в этом типе. Я не понимаю, почему он не может «наследовать» его от A, если компилятор уже может понять, что это необходимо?

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

Возможно, есть веская причина для текущего поведения, я просто не мог найти/выяснить, что это такое.

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

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

Или это связано с некоторыми трудностями при правильной его реализации?

Я мог бы найти несколько дискуссий по теме (например, self type is not inherited), но они в основном просто указывают на проблему и заключают, что это так, что она не содержит слишком много объяснений и/или решения (если оно существует).

ответ

1
trait C extends B with A 

- не единственное решение. Вы также можете иметь

trait AA extends A 
trait C extends B with AA 

То есть, все, что унаследованный интерфейс A принимается. Если вы должны полагаться на конкретную реализацию, вы бы выбрали mixin; если реализация зависит от пользователя или у вас есть веская причина не указывать миксин в признаке (например, чтобы ослабить проблемы с зависимостями), вы сделаете его самонастраивающимся.

+1

Я думаю, для меня ясно, в чем разница между смешением в признаке или созданием его типа. Мой вопрос: если предположить, что я хочу, чтобы предыдущие черты были с самим типом и смешением, как есть, и компилятор может понять, что мне нужно (по крайней мере) A, как сам тип C, почему он не может автоматически «добавить» его? –

+0

Я думаю, что это было бы нежелательно во многих случаях, как это было бы тогда компилировать, не давая вам возможности специализироваться на классе. И что делать, когда 'A' ​​недоступно в текущей области? Я считаю, что это будет путать, и что наследование и смешение должны быть ясными. Кроме того, если вы хотите сохранить ввод текста, вы можете определить, что 'trait CA расширяет C с A' и использует это. – Debilski

+1

Дебильски, вы недопонимаете вопрос. OP хочет, чтобы «trait C extends B» был эквивалентен «trait C extends B {this: A =>}», а не «trait C extends B with A». – Blaisorblade