0

Can I have a class that can have two different self types in Scala? Or emulate it in some way?

object Hi {
    trait One {
        val num = 1
    }
    trait Two {
        val num = 2
    }
    class Test {
        this: One => {
            println(num)
        }
        this: Two => {
            println(num)
        }
    }
}

import Hi._
new Test with One
new Test with Two
mdenton8
  • 619
  • 5
  • 13
  • 1
    Not even close to a duplicate. That question asks for multiple self-types at the same time, in order to follow a single block of execution. I am asking to branch based on being different self-types; i.e., do things conditionally based on my self-type. – mdenton8 Apr 10 '15 at 02:54

2 Answers2

4

Subtyping:

scala> trait Num { def num: Int }
defined trait Num

scala> trait One extends Num { val num = 1 }
defined trait One

scala> trait Two extends Num { val num = 2 }
defined trait Two

scala> class Test { _: Num => def f() = println(num) }
defined class Test

scala> new Test with One
res0: Test with One = $anon$1@389adf1d

scala> .f()
1

Edit: Maybe that was a knee-jerk response and I should have said typeclasses.

som-snytt
  • 39,429
  • 2
  • 47
  • 129
  • Nice! Thank you. Can't believe I didn't think of that. How about with arbitrary different traits? I suppose I can just define an arbitrary catch-all method... – mdenton8 Aug 19 '14 at 21:43
  • 1
    "How about with arbitrary different traits?" You can use a structural type as the self-type: `class Test { this: { def num: Int } => ...}`. I haven't tested in detail, but it compiles at least. – Alexey Romanov Aug 20 '14 at 06:14
2

If you want to have multiple self-types simultaneously, you can write this: One with Two => .... Having two separate self-types, as in your example, just doesn't make much sense to me: if you have two different bodies (with different method implementations, different members, etc.) why not just make them into two separate classes/traits?

Alexey Romanov
  • 167,066
  • 35
  • 309
  • 487
  • It made a kind of sense to me: I can be mixed in with A or B, if I'm A, behave this way, etc. It localizes the differential behavior. Not saying it's desirable. Maybe the syntax would be `case this: One => `. – som-snytt Aug 20 '14 at 06:18
  • I had a use case where multiple self types would have been perfect, and made the most sense out of any of the alternatives, but I can't remember it now. – mdenton8 Aug 20 '14 at 06:28