2013-05-09 4 views
2

У меня есть набор моделей, каждый из которых предоставляет следующий (...) метод, который перемещает модель вперед на дискретном шаге. Каждый следующий() метод имеет параметр, заданный абстрактным типом Т.Проекция типа Scala

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

Мое решение было бы использовать прогнозы типа так:

trait Model { 
    type T // works fine when this is a concrete implementation, but then cannot be overridden 
    def next(input : T) = println(input) 
} 

abstract class Parent { 
    type S <: Model 
    type T = S#T 
    val model : S 
    def next(input : T) = model.next(input) 
} 

Это завершается с ошибкой компилятора: типа несоответствия; найдено: input.type (с базовым типом Parent.this.T) требуется: Parent.this.model.T

Обратите внимание, что в любой конкретной реализации Parent Parent.this.T должен быть равен Parent.this .model.T.

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

+1

Чтобы исправить ошибку, просто замените 'type T = S # T' на' type T = model.T', но я не могу понять вашу цель. – senia

+0

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

+0

У вас есть 2 модели: с 'T = Int' и' T = String', как они могут быть совместимы? – senia

ответ

3

Кредиты идут на @senia. Установка type T = model.T работает просто отлично:

abstract class Parent { 
    type S <: Model 
    type T = model.T 
    val model : S 
    def next(input : T) = model.next(input) 
} 

class SimpleParent[GT <: Model](val model: GT) extends Parent { 
    type S = GT 
} 

trait StringModel extends Model { type T = String } 
trait IntModel extends Model { type T = Int } 

object Test { 
    new SimpleParent(new StringModel {}) 
    new SimpleParent(new IntModel {}) 
} 

Посмотрите на here, чтобы понять, почему type T = S#T не работает. (Короткий вариант: мы могли бы иметь model.type <: S и S#T не бетонные, следовательно S#T может быть несовместим с model.T).

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