2017-01-17 1 views
1

Так что у меня проблемы с тем, что, по моему мнению, довольно простая ситуация в реализации признаков, и я надеюсь, что есть какое-то простое решение, которое мне не хватает. Я хотел бы иметь метод на черта, которая принимает в качестве параметра (и возвращает в качестве значения только тип конкретной реализации, что она вызывается на частности:.Метод метода Scala ограничен внедрением типа

trait Foo { 
    type ConcreteFoo // what to put here? 
    def combine(that:ConcreteFoo):ConcreteFoo 
} 

class FooImpl1 extends Foo { 
    def combine(that:FooImpl1):FooImpl1 = { 
    // implementation 
    } 
} 

class FooImpl2 extends Foo { 
    def combine(that:FooImpl2):FooImpl2 = { 
    // implementation 
    } 
} 

Прямо сейчас у меня есть type Self = FooImpl на классы реализации, но я предпочел бы что-то на черта, которая заботится о нем, если это возможно

+0

Решение называется 'f-bounded polymorphism'. Читайте здесь: https://twitter.github.io/scala_school/advanced-types.html#fbounded – maasg

ответ

1

Это точно F-Bounded Polymorphism:

trait Foo[T <: Foo[T]] 
    def combine(that: T): T 
} 

class FooImpl1 extends Foo[FooImpl1] { 
    def combine(that: FooImpl1): FooImpl1 = { 
    ??? 
    } 
} 

class FooImpl2 extends Foo[FooImpl2] { 
    def combine(that: FooImpl2): FooImpl2 = { 
    ??? 
    } 
} 
+0

Отлично! Я помню, хотя почему я не принял этот подход изначально. 'Foo' также принимает параметры типа, поэтому, когда я не хочу ограничиваться конкретной реализацией Foo, я не знаю, как это сделать без параметров размножающегося типа во всем мире. то есть. 'trait Foo [A, F <: Foo [A, F]]; def accumulate (f: Foo [A, _]) 'fail, потому что' _' не удовлетворяет оценке, но я не вижу, как его заполнять. –

+0

@John Вы можете выполнить 'def accumulate (f: F)', так как он уже связан декларацией признаков. –

+0

Извините, я не понял этого фрагмента. 'accumulate' не определен в' Foo', но в другом месте для общих 'Foo'. Поэтому на самом деле представьте себе что-то вроде 'def accumulate [A] (f: Foo [A, _])'. Я знаю, что я мог бы выполнить 'def accumulate [A, F <: Foo [A, F]] (f: F)', но это именно «распространение параметров типа, которые я хочу избежать». Есть ли какие-либо причины для предоставления стираемого параметра типа с соответствующими границами в этом случае? Очевидно, что наивный подход дает бесконечный регресс: 'def накапливать [A] (f: Foo [A, _ <: Foo [A, _ <: Foo [A, _ ...]])' –

0

Вы можете добавить параметр типа к вашему признаку, как это:.

trait Foo[A] { 
    def combine(that: A): A 
} 

class FooImpl1 extends Foo[FooImpl1] { 
    override def combine(that: FooImpl1): FooImpl1 = ??? 
} 

class FooImpl2 extends Foo[FooImpl2] { 
    override def combine(that: FooImpl2): FooImpl2 = ??? 
} 
Смежные вопросы