3

I am trying to expose a class parametrized with a type alias:

trait Tr[T] {
  var x: T = _
}

abstract class Foo {
  type MyParameter

  class SomeClass extends SomeOtherClass with Tr[MyParameter]
}

class Bar extends Foo {
  override type MyParameter = Int

  val myObj = new SomeClass
  myObj.x = 6
}

class Qux extends Foo {
  override type MyParameter = String

  val myObj = new SomeClass
  myObj.x = "hello" 
}

This works fine.

Now, what I would like to do is to specify a default value for the MyParameter type. Like this:

abstract class Foo {
  type MyParameter = String
  // ...
}

// ...

class Qux extends Foo {
  val myObj = new SomeClass
  myObj.x = "hello"
}

If I do this, however, class Bar will fail with a type error -- apparently, at that point, SomeClass is already fixed to String.

What can I do to fix this? Alternately, what other approach can I take to have SomeClass parametrized by a type that has a default, but can be overriden in subclasses of Foo?

Note that SomeClass will be more complex than shown, so I don't want the users to have to override the definition of SomeClass. Also, all uses of X.SomeClass should use the same Tr[T], so I don't want to make SomeClass itself parametrizable.

1 Answer 1

1

If you omit the assignment you can get to the root cause of the issue:

scala> :paste
// Entering paste mode (ctrl-D to finish)

trait T[T] {
  var x: T = _
}

abstract class Foo {
  type Param = String

  class Child extends T[Param]
}

class Bar extends Foo {
  (new Child).x = "foo"
}

class Qux extends Foo {
  override type Param = Int
}

// Exiting paste mode, now interpreting.

<pastie>:26: error: overriding type Param in class Foo, which equals String;
 type Param has incompatible type
  override type Param = Int

Overriding a type follows the same rules as overriding a def, val or var: the overriding type has to be compatible with the type it is overriding.

The same way you can't override toString to return an Int, for example.

scala> :paste
// Entering paste mode (ctrl-D to finish)

class Test {
  override def toString: Int = 1
}

// Exiting paste mode, now interpreting.

<pastie>:12: error: overriding method toString in class Object of type ()String;
 method toString has incompatible type
  override def toString: Int = 1
               ^

My suggestion would be to split the hierarchy, so when you need a Foo that has a Tr[String] into a FooString, and if you need other type you can extend Foo.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.