2013-05-17 2 views
1

У меня есть абстрактный класс с методом, который принимает список поплавков в качестве параметра:Как перегрузить супер класс метод

abstract class a { 
    def m(p: List[Float]) { 
     println("Passed List[Float] to p()") 
    } 
} 

Я хочу перегружать м в бетоне простирающейся класс:

class b extends a { 
    def m(p: List[Double]) { 
     println("Passed List[Double] to p()") 
    } 
} 

Есть ли способ сделать это? Когда я пытаюсь это, я получаю эту ошибку:

error: name clash between defined and inherited member: 
method m:(p: List[Double])Unit and 
method m:(p: List[Float])Unit in class a 
have same type after erasure: (p: List)Unit 
    def m(p: List[Double]) { 

ответ

1

Вы должны изменить подпись как-то, так что вам нужен фиктивный аргумент.

abstract class A { 
    def m(p: List[Float]) { println(p.sum) } 
} 

class B extends A { 
    def m(p: List[Double])(implicit dummy: Unit =()) { println(p.product) } 
} 

и теперь

scala> val b = new B 
b: B = [email protected] 

scala> { b.m(List(3.0f,3.0f)); b.m(List(3.0, 3.0)) } 
6.0 
9.0 

Yay!

С другой стороны, это может сделать вещи менее удобными.

scala> val a = new A {} 
a: A = [email protected] 

scala> a.m(List(3,3)) 
6.0 

scala> b.m(List(3,3)) 
<console>:11: error: overloaded method value m with alternatives: 
    (p: List[Double])(implicit dummy: Unit)Unit <and> 
    (p: List[Float])Unit 
cannot be applied to (List[Int]) 
       b.m(List(3,3)) 
       ^

Не то, что вы знаете, какой был правильным в любом случае, с b. Таким образом, это защищает вас от ошибок, но ценой не выведения правильного типа (поскольку это неверно, это неоднозначно).

2

Существует override ключевое слово для этого, однако в этом случае проблема TypeErasure во время компиляции. Первый метод принимает List[Float], а другой - List[Double].

Эти типы будут удалены, поэтому вы получите два метода, которые принимают List и возвращают Unit. Это столкновение.

Изменить имя

Теперь простое разрешение, чтобы дать им разные имена.

Использование дженериков

abstract class a[T] { 
    def m(p: List[T]) { 
     println("Passed List[Float] to p()") 
    } 
} 

class b extends a[Double] { 
} 
+0

Я не хочу, чтобы переопределить, я хочу перегружать. Так что любая версия m() может быть вызвана в зависимости от типа аргумента. – bwroga

+0

Вместо этого вы можете использовать Массивы. Массивы Scala отображаются непосредственно в массивы Java, которые не реализованы с помощью дженериков. Таким образом, информация типа фактически остается с массивом во время выполнения. – GJK

1

Я не уверен, что именно вы пытаетесь сделать здесь, но у меня есть другое предложение для вас

abstract class A { 
    protected def _m(p: List[Float]) { 
    } 
} 

class B extends A { 
    def m(p: List[Double]){ 
    _m(p.map(_.toFloat)) 
    } 
} 

class C extends A { 
    def m(p: List[Float]) { 
    println("Passed List[Float] to p()") 
    _m(p) 
    } 
} 
Смежные вопросы