Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's the rule to implement an method in trait?

I defined a trait:

trait A {
   def hello(name:Any):Any
}

Then define a class X to implement it:

class X extends A {
  def hello(name:Any): Any = {}
}

It compiled. Then I change the return type in the subclass:

class X extends A {
  def hello(name:Any): String = "hello"
}

It also compiled. Then change the parameter type:

class X extends A {
  def hello(name:String): Any = {}
}

It can't compiled this time, the error is:

error: class X needs to be abstract, since method hello in trait A of type (name: Any)
Any is not defined
(Note that Any does not match String: class String in package lang is a subclass 
of class Any in package scala, but method parameter types must match exactly.)

It seems the parameter should match exactly, but the return type can be a subtype in subclass?


Update: @Mik378, thanks for your answer, but why the following example can't work? I think it doesn't break Liskov:

trait A {
   def hello(name:String):Any
}

class X extends A {
   def hello(name:Any): Any = {}
}
like image 401
Freewind Avatar asked Jan 10 '23 18:01

Freewind


1 Answers

It's exactly like in Java, to keep Liskov Substitution principle, you can't override a method with a more finegrained parameter.

Indeed, what if your code deals with the A type, referencing an X type under the hood. According to A, you can pass Any type you want, but B would allow only String. Therefore => BOOM

Logically, with the same reasonning, a more finegrained return type is allowed since it would be cover whatever the case is by any code dealing with the A class.

You may want to check those parts: http://en.wikipedia.org/wiki/Covariance_and_contravariance_(computer_science)#Covariant_method_return_type

and

http://en.wikipedia.org/wiki/Covariance_and_contravariance_(computer_science)#Contravariant_method_argument_type

UPDATE----------------

trait A {
   def hello(name:String):Any
}

class X extends A {
   def hello(name:Any): Any = {}
}

It would act as a perfect overloading, not an overriding.

like image 159
Mik378 Avatar answered Jan 18 '23 19:01

Mik378