Я очень новичок в scala, и поиск новых шаблонов для scala продолжается.
Цель состоит в том, чтобы разделить обработку сообщений и генерацию сообщений. Существует базовый ковариантный параметризованный тип, представляющий обработку сообщений. Конкретная реализация может сочетаться с обычным миксином или путем смешения базовых протоколов.
Требования:
Удлинение как можно большего размера
Будьте бдительны во избежание глупых ошибок
Я пришел с чистым примером кода (содержит как определение, так и использование):
trait Protocol
trait Handler [+proto <: Protocol] {
def handle : PartialFunction[Protocol,Unit]
/* can not name the actual protocol type since handler for a subtype also fully supports handling supertype
besides any message extends other subtype ot the supertype since the scala use matching with case classes
and these algebraic type realization is seemed excluded from strait scala type system
*/
}
/*
==============
using scenario
==============
*/
trait SumMsg extends Protocol
case class Sum(op : Int) extends SumMsg
case class Sub(op : Int) extends SumMsg
trait ProdMsg extends Protocol
case class Mul(op : Int) extends ProdMsg
case class Diff(op : Int) extends ProdMsg {
require (0 != op, "Division by zero is not permited")
}
/* stackable traites */
trait NullHandler {
def handle : PartialFunction[Protocol,Unit] = { case _ => {} }
}
trait SumHandler extends Handler [SumMsg] with NullHandler{
var store : Int
abstract override def handle : PartialFunction[Protocol,Unit] = ({
case Sum(op) => { this.store += op}
case Sub(op) => { this.store -= op}
}: PartialFunction[Protocol,Unit]) orElse super.handle
}
trait MulHandler extends Handler [ProdMsg] with NullHandler{
var store : Int
abstract override def handle : PartialFunction[Protocol,Unit] = ({
case Mul(op) => {this.store *= op}
case Diff(op) => {this.store /= op}
}: PartialFunction[Protocol,Unit]) orElse super.handle
}
/* concrete classes */
class SumAccum (var store: Int) extends SumHandler
class MulAccum (var store: Int) extends MulHandler
class ArithmAccum (var store: Int) extends SumHandler with MulHandler
/* producers */
class ProduceSums (val accum : Handler [SumMsg]) {
var state : Boolean = true
def touch() = if (this.state)
{
this.state = false
this.accum.handle(Sum(2))
} else {
this.state = true
this.accum.handle(Sub(1))
}
}
class ProduceProds (val accum : Handler [ProdMsg]) {
var state : Boolean = true
def touch() = if (this.state)
{
this.state = false
this.accum.handle(Mul(2))
} else {
this.state = true
this.accum.handle(Diff(2))
}
}
/* tying together via cake pattern */
trait ProtocolComp {
type Proto <: Protocol
}
trait ProducerComp { this: ProtocolComp =>
type ProducerT <: {def touch()}
def getProducer(accum : Handler[Proto]) : ProducerT
}
trait HandlerComp { this: ProtocolComp =>
type HandlerT <: Handler[Proto]
def getHandler(store:Int) : HandlerT
}
trait AppComp extends ProtocolComp with ProducerComp with HandlerComp {
val initStore = 1
def test() {
val handler = getHandler(initStore)
val producer = getProducer(handler)
producer.touch()
}
}
/* different examples of compositions */
/* correct usage */
object One extends AppComp{
override type Proto = SumMsg
override type ProducerT = ProduceSums
override type HandlerT = SumAccum
override def getProducer(accum : Handler[Proto]) = new ProduceSums(accum)
override def getHandler(store : Int) = new SumAccum(store)
}
object Two extends AppComp{
override type Proto = SumMsg
override type ProducerT = ProduceSums
override type HandlerT = ArithmAccum
override def getProducer(accum : Handler[Proto]) = new ProduceSums(accum)
override def getHandler(store : Int) = new ArithmAccum(store)
}
object Three extends AppComp{
override type Proto = SumMsg with ProdMsg
override type ProducerT = ProduceSums
override type HandlerT = ArithmAccum
override def getProducer(accum : Handler[Proto]) = new ProduceSums(accum)
override def getHandler(store : Int) = new ArithmAccum(store)
}
/* incorrect usage
static type checking protects from some kind of logic errors
*/
object Four extends AppComp{
override type Proto = SumMsg
override type ProducerT = ProduceProds
override type HandlerT = SumAccum
override def getProducer(accum : Handler[Proto]) = new ProduceProds(accum)
override def getHandler(store : Int) = new SumAccum(store)
}
Последний пример напечатан неправильно и выдает ошибку, как и ожидалось:
mixed.scala:140: error: type mismatch;
found : Handler[Four.Proto]
required: Handler[ProdMsg]
override def getProducer(accum : Handler[Proto]) = new ProduceProds(accum)
Я построил гибкую систему с простым объединением и расширением, но при этом максимально безопасную для использования классов падежей scala вместо алегратических типов
Я почти достиг своей цели, но столкнулся с большой ошибкой в scala: стиранием типа базового jvm. Использованные мною конструкции недопустимы для scala, так как я хочу, чтобы параметризованная черта расширялась с помощью предложения «with».
Компилятор жалуется на
mixed.scala:53: error: illegal inheritance;
class ArithmAccum inherits different type instances of trait Handler:
Handler[ProdMsg] and Handler[SumMsg]
class ArithmAccum (var store: Int) extends SumHandler with MulHandler
Какие варианты у меня есть? Я не могу использовать шаблон, который я разработал, и мне нужно найти равную замену юзабилити. Может ли кто-нибудь предложить альтернативное решение для исходного кода? Существует ли плагин Scala (они, похоже, существуют для компилятора) или другой метод, позволяющий изменить бэкенды для параметризованных типов Scala с обобщенных java-приложений на c ++, как генерация кода?