I am using several classes like this:
class MyClassOne {
doSomething(a : A) : B
...
}
class MyClassTwo {
doSomething(a : A) : B
...
}
The source for the classes is not under my control. Although the classes have methods with the same signature they don't implement an interface. I would like to define methods that work on all the classes.
So I've made a Trait like this:
trait MyTrait {
doSomething(a : A) : B
}
And have made implicit conversions for all the classes:
implicit class MyClassOneMyTrait(myClassOne : MyClassOne) {
def doSomething(a : A) = myClassOne.doSomething(a)
}
Is there a way to take advantage of the naming conventions used in the classes and avoid explicitly delegating to the objects passed into the constructor? More generally, is using a Trait with implicit classes the best approach to this problem?
Actually, there is scala feature exactly for your situation. It's called structural types.
For structural types type requirements are expressed by interface structure instead of a concrete type. Internal implementation uses reflection, so be performance-aware!
type A = String
type B = String
class MyClassOne {
def doSomething(a: A): B = {
println("1")
"1"
}
}
class MyClassTwo {
def doSomething(a: A): B = {
println("2")
"2"
}
}
type MyClassType = {
def doSomething(a: A): B
}
List[MyClassType](new MyClassOne, new MyClassTwo).foreach(_.doSomething("test"))
List(new MyClassOne, new MyClassTwo).foreach {
case a: MyClassType => a.doSomething("test")
case _ =>
}
Related
I discovered that using abstract types affects the scala compiler ability to detect overrides and it interprets seemingly correct code as erroneous.
trait I {
type T
def doThings(t : T) : Unit
}
type IT[X] = I { type T = X}
trait A extends I {
override type T = AnyRef
def doThings(t : T) : Unit = println("A")
}
trait Z[X] extends I { this : IT[X] =>
abstract override def doThings(t : T) : Unit = {
println("Z")
super.doThings(t)
}
}
object Use {
val az = new A with Z[AnyRef] {}
}
The scala compiler fires such error:
OverloadAbstract.scala:44: error: object creation impossible, since method doThings in trait Z of type (t: this.T)Unit is marked `abstract' and `override', but no concrete implementation could be found in a base class
val az = new A with Z[AnyRef] {}
What is the proper way to express such relations between trait mixing and implementation?
For the comparison that code works fine:
trait I {
def doThings() : Unit
}
class A extends I {
def doThings() : Unit = println("A")
}
trait Z extends I {
abstract override def doThings() : Unit = {
println("Z")
super.doThings()
}
}
object Use {
val az = new A with Z {}
}
The real use case is to implement a forwarder for the akka.event.EventBus:
object PartialEventBus {
type ApplyEvent[E] = EventBus { type Event = E }
}
trait ForwardEventBus[E] extends EventBus { this : PartialEventBus.ApplyEvent[E] =>
def relay : PartialEventBus.ApplyEvent[E]
abstract override def publish(event : Event) : Unit = {
relay.publish(event)
super.publish(event)
}
}
Type parametrization for the ForwardEventBus is needed for compiler to match object-wide this.Event type with external relay.Event type. Compiler would fail without such hint because of scala's path-dependent types restrictions.
Perhaps I'm confused, shouldn't the question be "Why does abstract override succeed?" Section 5.2.4 of the spec covers abstract override, and it says, "The override modifier has an additional significance when combined with the abstract modifier. That modifier combination is only allowed for value members of traits."
I hope a language lawyer can weigh in, but it looks like this should not be legal.
I have few classes which do not derive from any superclass. They all have bunch of same methods defined. For example,
class A {
def getMsgNum = 1
}
class B {
def getMsgNum = 2
}
I would like to write a generic function that will return message num based on object function is called with. So something like,
def getMsgNum[T](t: T) = t.getMsgNum
I think that because of type erasure I cannot expect that to work but I was looking at view bound and context bound with ClassTag but that still does not work.
def getType[T: ClassTag](msg: T) = {
msg.getMsgNum
}
I come from C++ background and I am trying to achieve something to the effect of template compilation for every type.
Thanks for your time!
I personally prefer adhoc polymorphism with TypeClass (http://danielwestheide.com/blog/2013/02/06/the-neophytes-guide-to-scala-part-12-type-classes.html) pattern. I think it will be much more "true scala way" solution for this kind of problem. Also structural typing more expensive at runtime because it use reflection for field access.
class A
class B
trait ToMsgNum[T] {
def getMsgNum: Int
}
implicit object AToMsgNum extends ToMsgNum[A] {
def getMsgNum = 1
}
implicit object BToMsgNum extends ToMsgNum[B] {
def getMsgNum = 2
}
def getMsgNum[T: ToMsgNum](t: T) =
implicitly[ToMsgNum[T]].getMsgNum
println(getMsgNum(new A))
println(getMsgNum(new B))
def getMsgNum[T](t: T)(implicit ev: T => { def getMsgNum: Int }) = t.getMsgNum
where { def getMsgNum: Int } is a structural type. From the documentation:
A structural type is a type of the form Parents { Decls } where Decls contains declarations of new members that do not override any member in Parents.
and
Structural types provide great flexibility because they avoid the need to define inheritance hierarchies a priori
Please note that the above solution uses an implicit reflective call to access the field of the structural type, a language feature that has to be explicitly enabled by adding the import
import scala.language.reflectiveCalls
This is not too different from Eugene's solution but I think it's a bit clearer:
// predefined classes you have no access to
class Foo { def someMethod = "foo" }
class Bar { def someMethod = "bar" }
there's no way in Scala other than reflection or structural types (which is reflection in disguise) to generically call someMethod on these types. The way this can be made to work though, is by defining adapter objects that know how to deal with each type individually, and you then make generic calls on those instead:
trait HasSomeMethod[T] { def someMethod(x: T): String }
object FooHasSomeMethod extends HasSomeMethod[Foo] { def someMethod(x: Foo) = x.someMethod }
object BarHasSomeMethod extends HasSomeMethod[Bar] { def someMethod(x: Bar) = x.someMethod }
now you can pass one of those adapter objects into the method that needs generic access to Foo#someMethod and Bar#someMethod:
def invokeSomeMethod[T](x: T)(adapter: HasSomeMethod[T]) =
adapter.someMethod(x)
invokeSomeMethod(new Foo)(FooHasSomeMethod) // returns "foo"
invokeSomeMethod(new Bar)(BarHasSomeMethod) // returns "bar"
(we could have used a single parameter list here but later we'll nede 2 lists anyway)
however, this is obviously not as useful as we'd like as we have to pass in the adapter manually. Let's introduce implicits to make Scala automatically look up the right adapter object and pass that in to our generic but inheritance'less method:
implicit object FooHasSomeMethod extends HasSomeMethod[Foo] { ... }
implicit object BarHasSomeMethod extends HasSomeMethod[Bar] { ... }
def invokeSomeMethod[T](x: T)(implicit adapter: HasSomeMethod[T]) =
adapter.someMethod(x)
now these work:
invokeSomeMethod(new Foo) // returns "foo"
invokeSomeMethod(new Bar) // returns "bar"
The above 2 calls get translated automatically to the longer calls in the previous version; Scala looks up suitable values for the implicit adapter parameter automatically from the implicit objects (and also vals and defs, to be precise) available in the "environment" of the call.
You can also define invokeSomeMethod like this, which is just syntactic sugar over the above definition:
def invokeSomeMethod[T: HasSomeMethod](x: T) =
implicitly[HasSomeMethod[T]].someMethod(x)
or, since T: HasSomeMethod auto-generates a second parameter list implicit evidence$1: HasSomeMethod[T], this also works:
def invokeSomeMethod[T: HasSomeMethod](x: T) =
evidence$1.someMethod(x)
The above "pattern" is known as Type Classes. So for example the T: HasSomeMethod bit can be read as "some type T that belongs to the type class HasSomeMethod" (or "...has been made an instance of the type class HasSomeMethod").
For more on Type Classes, see e.g. http://danielwestheide.com/blog/2013/02/06/the-neophytes-guide-to-scala-part-12-type-classes.html.
You can also define the HasSomeMethod type class instance for classes that don't even have someMethod nor bear no other resemblance to Foo and Bar whatsoever, if needed:
implicit object IntHasSomeMethod extends HasSomeMethod[Int] {
def someMethod(x: Int) = "this is an int: " + x
}
invokeSomeMethod(3) // returns "this is an int: 3"
If you need to define an instance of that type class for many classes, you can have a helper (with a name that matches the type class, for niceness):
def HasSomeMethod[T](fn: T => String) = new HasSomeMethod[T] {
def someMethod(x: T) = fn(x)
}
now you can define type class instances (adapters) very concisely:
implicit val FooHasSomeMethod = HasSomeMethod[Foo](_.someMethod)
implicit val BarHasSomeMethod = HasSomeMethod[Bar](_.someMethod)
implicit val IntHasSomeMethod = HasSomeMethod[Int]("this is an int: " + _)
implicit val PersonHasSomeMethod = HasSomeMethod[Person](_.name)
// etc
If you dont want to use structural type (reflection) and implicit, how about create Adaptor on top of it, so you own method getMsgNum will implement based on the Adaptor instead of already existing class.
class A {
def getMsgNum = 1
}
class B {
def getMsgNum = 2
}
class C {
def getMsgNum = 3
}
trait Adaptor[T] {
def getMsgNum: Int
}
class AdaptorA(t: A) extends Adaptor[A] {
def getMsgNum = t.getMsgNum
}
class AdaptorB(t: B) extends Adaptor[B] {
def getMsgNum = t.getMsgNum
}
class AdaptorC(t: C) extends Adaptor[C] {
def getMsgNum = t.getMsgNum
}
def getMsgNum[T](t: Adaptor[T]) = t.getMsgNum
getMsgNum(new AdaptorA(new A)) //1
getMsgNum(new AdaptorB(new B)) //2
getMsgNum(new AdaptorC(new C)) //3
I have the following trait hierarchy. TraitA is the root trait, and given that I want my data structures to be immutable, the function commonUpdateFunction() has a generic return type. I am not sure if this is the best way. I have two other traits that extend it, adding two other functions. Some classes extend one, some classes extend the other, but some classes need to extend both.
However, I am now running into a problem where because of that generic type thing I am getting illegal inheritance, when in reality I am only doing it to get the right type when updating the data structure to a new one.
Furthermore it seems I cannot pass TraitA as a parameter because of this generic type.
trait TraitA[T <: TraitA[T]]
{
self : T =>
def commonUpdateFunction() : T
}
trait TraitB extends TraitA[TraitB]
{
def someFunctionB() : Integer = { /// some code }
}
trait TraitC extends TraitA[TraitC]
{
def someFunctionC() : Unit = { /// some code }
}
class ClassB extends TraitB
{
def commonUpdateFunction() : ClassB = { /// some code }
}
class ClassC extends TraitC
{
def commonUpdateFunction() : ClassC = { /// some code }
}
class ClassA extends TraitB with TraitC //**this causes illegal inheritance**
{
def commonUpdateFunction() : ClassA = { /// some code }
}
What is the right way to achieve this inheritance on 2 traits while at the same time having immutable updating of data structures with the right types?
Type parameters aren't your problem here, the problem is that ClassA tries to mix in three copies of commonFunction(), which differ only by return type:
class ClassA extends TraitB with TraitC {
def commonFunction() : ClassA = { /// some code }
def commonFunction() : ClassB = { /// some code }
def commonFunction() : ClassC = { /// some code }
}
Although the JVM does allow overloading on return type, it isn't permitted at compile time - there's just too much chance for confusion (especially if type inference is involved).
The solution is often to use f-bounded polymorphism (as you did with commonUpdateFunction()), but it's impossible to show how to do that here given that all your commonFunction() definitions are concrete.
It would help a lot to see more "real" code!
UPDATE: Based on new information from the comments.
Instead of a type parameter you might find life easier with an abstract type member. Using Repr (for "Repr"esentation) is a common enough convention and used in the collections lib; make sure that this abstract type member has a bound!
Stick the other common attributes in here as well:
trait Employee {
type Repr <: Employee
def name : String
def id : Int
def withName(name: String) : Repr
def withId(id: Int) : Repr
}
sub-traits follow a similar pattern. There's no need to re-declare other abstract members that keep their signature. You can also introduce other members as you refine the types here.
trait ManagingEmployee extends Employee {
type Repr <: ManagingEmployee
def numberOfReports: Int
def withNumberOfReports(x: Int) : Repr
}
trait SkilledEmployee extends Employee {
type Repr <: SkilledEmployee
def skill: String
}
Now make the leaf nodes of our type tree concrete. case classes work well here, though there will sadly be some duplication (macros could possibly help, but that's a different question).
Note how name and id are made concrete by the class params, the Repr type is made explicit via the = sign, and the abstract methods have to be explicitly re-defined in each leaf class:
case class HrManager(
name : String,
id : Int,
numberOfReports : Int
) extends ManagingEmployee {
type Repr = HrManager
def withName(name: String) = this.copy(name = name)
def withId(id: Int) = this.copy(id = id)
def withNumberOfReports(x: Int) = this.copy(numberOfReports = id)
}
case class Technician(name: String, id: Int) extends SkilledEmployee {
type Repr = Technician
def withName(name: String) = this.copy(name = name)
def withId(id: Int) = this.copy(id = id)
val skill = "programming"
}
case class TechnicalManager(
name : String,
id : Int,
numberOfReports : Int
) extends SkilledEmployee with ManagingEmployee {
type Repr = TechnicalManager
def withName(name: String) = this.copy(name = name)
def withId(id: Int) = this.copy(id = id)
def withNumberOfReports(x: Int) = this.copy(numberOfReports = id)
val skill = "software architecture"
}
I'm attempting to make a system which allows users to chain together multiple processors. The difficulty I have is that each processor actually has two bits of information it cares about and I want these handled in a type-safe way. I've boiled it down to this problem:
Given:
//First family of stuff
trait A {
def doA {}
}
trait B {
def doB {}
}
//Second family of stuff
trait X {
def doX {}
}
trait Y {
def doY {}
}
I can combine elements from the two families together in 4 flavors:
var f = new A with X {}
f.doA
d.doX
var g = new A with Y {}
//...
Great. The problem is that I want each of the functions (doA, etc) to return a combination of the two types so that I can chain stuff together. Essentially I want to do:
trait A {
def doThing = {
new A with ThingThatImMixedInWithLikeXOrY {}
}
}
Each processor needs to return an anonymous class which consists of 1) A type known to the processor 2) The type which it was mixed in with.
My first stab was to use generics, something like this:
trait A {
this : {def makeWithT[TOther]} =>
def doA = makeWithT[B]
}
trait B {
this : {def makeWithT[TOther]} =>
def doB = makeWithT[A]
}
trait X {
this : {def makeWithS[TOther]} =>
def doX = makeWithT[Y]
}
trait Y {
this : {def makeWithS[TOther]} =>
def doY = makeWithT[Y]
}
class Foo[T, S] extends S with T {
def makeWithT[OtherT] = new T with OtherT
def makeWithS[OtherT] = new S with OtherT
}
var f = new Foo[A, X]
f.doA.doB
f.doX.doA
f.doX.doY
...
Obviously, I've run into a catalog of problems:
I can't make a generic class which extends from the type parameters
I can't instantiate my anonymous class via a generic parameter
I can't define the return type of the functions in the trait because I
don't know the type until it's mixed in with something.
I'm a bit of a noob when it comes to scala, and I get the feeling that I'm going about this in totally the wrong way and maybe I should be using implicits and the CanBuildFrom pattern. Any help would be greatly appreciated.
Cheers
The most known solution for stackable processors is stackable trait
http://www.artima.com/scalazine/articles/stackable_trait_pattern.html
trait StackableRoot {
def StackablePass (x:Int) : x
}
trait StackableDouble extends StackableRoot {
def internalPass (x:Int) = 2*x
abstract override def StackablePass(x:Int) = super.StackablePass(internalPass(x))
}
trait StackableIncrement extends StackableRoot {
def internalPass (x:Int) = x+1
abstract override def StackablePass(x:Int) = super.StackablePass(internalPass(x))
}
there is some boilerplate with
abstract override def StackablePass(x:Int) = super.StackablePass(internalPass(x))
that can't be avoided by packing into parametrized trait since it will require scala to inherit some trait with different parameters multiple times that is prohibited by famous type erasure
The access on Manifest seems to be tricky from a trait in scala.
How could this code compile in scala ?
trait SomeTraitOf[+A] {
def newInstanceOfA : A = /* necessary code to make it work */
}
(Related, it works fine as a parametized class :
class SomeTraitOf[A : Manifest] {
def newInstanceOfA(implicit m : Manifest[A]) : A =
m.erasure.newInstance.asInstanceOf[A]
}
but not with a covariant type parameter (+A))
Edit : The real stuff
sealed trait RootPeerProxy[+A] extends Proxy {
def peer: A
def self = peer
def peerManifest[B >: A](): Option[Manifest[B]]
private[scalavaadin] def newInstance() : Option[A]
}
trait PeerProxy[+A] extends RootPeerProxy[A] {
override def peerManifest[B >: A](): Option[Manifest[B]]
override def peer(): A = this.newInstance match {
case None => {throw new IllegalStateException("oups")}
case Some(a) => a
}
private[scalavaadin] override def newInstance() : Option[A] = peerManifest map { m => m.erasure.newInstance.asInstanceOf[A] }
}
Since traits cannot provide manifest for the parametized trait, the class implementing the trait should, but I am not getting it.
About covariance:
Since Manifest[A] is invariant in the parameter A, you can't do what you want directly. The usual strategy is to weaken the return type,
trait SomeTraitOf[+A] {
def newInstance[B >: A](implicit m: Manifest[B]): B = {
m.erasure.newInstance.asInstanceOf[B]
}
}
You can use the trait as follows,
class Parent
class Child extends Parent
val childBuilder = new SomeTraitOf[Child] {}
val parentBuilder: SomeTraitOf[Parent] = childBuilder
parentBuilder.newInstance // returns a Parent!
About View Bounds:
From your comment below, I guess you're also asking about "view bounds", which are just a concise way of declaring an implicit parameter. Your declaration
class SomeTraitOf[A : Manifest] { ...
basically translates to
class SomeTraitOf[A]()(implicit m0: Manifest[A]) { ....
Traits can't have view bounds because they can't take any (value) parameters. But that's not really a problem here, because in your example
class SomeTraitOf[A : Manifest] {
def newInstanceOfA(implicit m : Manifest[A]) : A =
m.erasure.newInstance.asInstanceOf[A]
}
you're not using the view bound! (You're using the parameter m instead.) If you wanted to use the view bound, you could do it this way:
class SomeTraitOf[A : Manifest] {
def newInstanceOfA : A =
implicitly[Manifest[A]].erasure.newInstance.asInstanceOf[A]
}