Давайте припустимо, що у мене є такий родовий тип, як цей:
class GenericEchoer[T <: Any] {
var content: T = _
def echo: String = "Echo: " + content.toString
}
Тоді можна створити міксин, який дозволив би розширити функціональність GenericEchoer [T] таким чином:
trait Substitution[T <: AnyRef] extends GenericEchoer[T] {
def substitute(newValue: T) = { content = newValue }
}
Визначивши ці дані, я можу створити тип таким чином:
val echoer = new GenericEchoer[Int] with Substitution[Int]
Моє запитання: як реалізувати подібну функціональність, щоб я міг опустити параметри типу в mixin? Іншими словами, мені б хотілося створювати один і той же тип за допомогою наступного рядка:
val echoer = new GenericEchoer[Int] with Substitution
Це, однак, не працює, оскільки Заміна "не знає" основний параметр типу.
Відповіді:
2 для відповіді № 1Ви невірно вказуєте код, він навіть не компілюється.
Твій GenericEchoer
не може бути class
, викликай своє content
member є абстрактним, або вам слід надати це за замовчуванням:
class GenericEchoer[T <: AnyRef] {
var content: T = _
def echo: String = "Echo: " + T.toString
}
Ви не можете писати T.toString
, я думаю, ти хотів content.toString
. Ви не можете пройти Int
йому, викликати Int
мав AnyVal
як його супертип і ваша верхня межа T
є AnyRef
.
self.content
в Substitution
Також є незаконним, вам слід:
1) зробити self
як селфітип:
trait Substitution[T <: AnyRef] extends GenericEchoer[T] { self =>
def substitute(newValue: T) = { self.content = newValue }
}
2) Замініть його на this
3) Просто піди { content = newValue }
Що стосується вашої проблеми. Ні, це неможливо. Я можу запропонувати вам замінити class
з trait
і введіть конструктор з абстрактним типом члена:
trait GenericEchoer {
type T <: AnyRef
var content: T = _
def echo: String = "Echo: " + content.toString
}
trait Substitution extends GenericEchoer {
def substitute(newValue: T) { content = newValue }
}
val enchoer = new GenericEchoer with Substitution { type T = String }
або краще
val enchoer = new GenericEchoer with Substitution {
type T = String
var content = "Hello" // either case it will be null
}