3
votes

I found this reading another question:

"[...] a trait that extends a class puts a restriction on what classes can extend that trait - namely, all classes that mix-in that trait must extend that class"

a little example:

class C 
trait U
trait T extends C 

class D extends U with T // does not work
class E extends T with U // works

Apparently when traits inherit from classes, you have to put the trait in the position that you would otherwise place a class in (i.e. directly after extends)

Now to my questions:

(extended the previous example)

class C 
class Test
trait U
trait T extends C 
trait Tst extends Test


class D extends U with T // does not work
class E extends T with U // works
class Test2 extends Tst with T
  • what do we do when we want to inherit form two different traits, where each of those two inherit from a different class? (see class Test 2) this doesn't seem to be possible
  • if we need to pay attention to the placement of traits that extend a class, how do traits work then? Are traits inheriting from classes not "normal" traits anymore?
2
I find traits inherting classes to be a bit peculiar. Do you have a concrete example showing why this is nessecary at all?Yuval Itzchakov
unfortunately not. I just read this in an example and was wondering myself. I'm new to scala, though not to OOP, and am yet to encounter something like this. I found it strange that the "position" of the trait can have an influence on the correctness, despite inheriting just from traits (as opposed to one class and multiple traits)user6454491

2 Answers

4
votes
  1. This is indeed impossible. You cannot inherit from two different classes at once, whether via traits or otherwise. This is unfortunate, but true. There is no very good reason for that AFAICT, it would be somewhat harder to implement, but not impossible, at least for scala (not "native java") classes. So apparently, it was just decided against at some point, seemingly without a good reason.

  2. Traits that extend classes aren't really "abnormal". It's more like the way scala compiler handles them is. Basically, anything, that is or extends a class has to appear in the extends clause, and not in with. Why? Well, why can you not compare Strings in java with ==? because ...

2
votes

Here's my guess: class can be defined with parameters, now let's imagine this:

class A(val x: Int) 
class B extends A(1)
class C extends A(2)
trait D extends B
trait E extends C

// Oops! x = ? Doesn't compile of course
class F extends D with E

UPDATE:

Disclaimer: I'm not an expert in C++

Here's how C++ is solving the diamond problem:

class A {
  int x;

public:
  A(int _x) {  x = _x; }
  int getX() { return x; };
};

class B : virtual public A {    
public:
  // B b; b.getX == 1
  B() : A(1) {}
};

class C : virtual public A {    
public:
  // C c; c.getX == 2
  C() : A(2) {}
};  

class D : public B, public C {
public:
  // I need to know that B/C inherit A
  // A(...) constructors defined above don't apply
  D(): B(), C(), A(3) {}
};

I guess that's exactly the problem Scala is trying to avoid.