Я думаю, что порядок наследования может быть тем, который вы ищете. Если вы замените " extends "
на тот, который показывает, какой метод какой черты называется:
trait Base {
def name = "Base"
def func = "Base." + name
}
trait A extends Base {
override def name = "A"
override def func = name + " A.extends " + super.func
}
trait B extends Base {
override def name = "B"
override def func = name + " B.extends " + super.func
}
val x = new Base with A with B
println(x.func)
// B B.extends B A.extends Base.B
Просто name
всегда "B"
. Другими словами:
trait Base { def func = "Base" }
trait A extends Base { override def func = "A extends " + super.func }
trait B extends Base { override def func = "B extends " + super.func }
val x = new Base with A with B
println(x.func)
// B extends A extends Base
что ты и хочешь ...
Полная линеаризация вашего примера:
Object, B, A, Base, ScalaObject, AnyRef, Any
(см. http://ofps.oreilly.com/titles/9780596155957/ScalaObjectSystem.html#Linearization для практического объяснения того, как вычислить линеаризацию)
Изменить, чтобы ответить на комментарий: Почему name
всегда возвращает "B"
? Это потому, что метод def name
переопределяется чертой B
для возврата "B"
. В этом весь смысл наследования, чтобы иметь возможность использовать поведение суперклассов, которое уточняется в подклассах:
trait Legs {
def legs: Int
def printLegs() { println("I have " + legs + " legs") }
}
class Dog extends Legs { def legs = 4 }
class Chicken extends Legs { def legs = 2 }
new Dog printLegs
// I have 4 legs
new Chicken printLegs
// I have 2 legs
legs
в признаке Legs
не является отдельным от legs
в Dog
в зависимости от того, ссылаетесь ли вы на него в Legs
или Dog
... Аналогично, ваш def name
всегда будет верните "B"
, если ваш объект B
.
Похоже, вы хотите использовать имя в качестве частного метода:
trait Base {
private def _name() = "Base"
def func = _name
}
trait A extends Base {
private def _name() = "A"
override def func = _name + " extends " + super.func
}
trait B extends Base {
private def _name() = "B"
override def func = _name + " extends " + super.func
}
val x = new Base with A with B
println(x.func)
// B extends A extends Base
Я считаю, что если нет четкой объектной модели, использование признаков и наследования быстро усложняется. Я предполагаю, что вы продезинфицировали / упростили пример, чтобы использовать общие имена, такие как A, B, Base, func
, чтобы вы поняли суть проблемы, но с другой стороны, это не дает мне никакой информации о том, какие изменения вы могли бы сделать, чтобы заставить его работать для тебя. Как вы и просили, я расположил код так, чтобы он печатал "B extends A extends Base"
. Я уверен, что есть ряд других ограничений, которые не в том, почему это не будет работать для вас.