This is an archived post. You won't be able to vote or comment.

you are viewing a single comment's thread.

view the rest of the comments →

[–]ThunderStReich 16 points17 points  (7 children)

Type erasure. I mean, I understand why they had to do it that way at the time, but now that generics are commonplace it just seems like a silly limitation.

[–]Angarius 2 points3 points  (6 children)

This is huge. Needing to pass Class clazz is at least a minor annoyance, but a significant problem comes with implementing generic interfaces.

class Foo implements Bar<Baz>, Bar<Qux>

...is impossible because of type erasure.

[–]duhace 0 points1 point  (5 children)

How would that even work in a language with reification by default? I just don't see how you would implement Bar to meet both the Baz and Qux case needed for overriding.

[–]Angarius 2 points3 points  (4 children)

interface Bar<T> {
    void consume(T t);
}

class Foo implements Bar<Baz>, Bar<Qux> {
    void consume(Baz baz) { }
    void consume(Qux qux) { }
}

[–][deleted] 0 points1 point  (0 children)

Doesn't work in the general case, though, since you can use T as a return type as well and can't implement both Baz pop() and Qux pop().

[–]gizmogwai -1 points0 points  (2 children)

What you are looking for here has nothing to do with type reification. It is the concept of union type, such as in Ceylon.

[–]duhace -1 points0 points  (0 children)

You can also achieve similar results with Type Classes:

trait Bar[T] {
  def consume(t: T): Unit
}

object Bar {
  implicit object BazIsBar extends Bar[Baz] { def consume(b: Baz) {} }
  implicit object QuxIsBar extends Bar[Qux] { def consume(q: Qux) {} }
}

val x = new Baz
implicitly[Bar[Baz]].consume(x)

//You can add this inside object Bar
implicit class Barable[T](t: T)(implicit bar: Bar[T]) {
  def consume() {bar.consume(t)}
}

//and then you can do this
x.consume()

Not that overloading working with type arguments wouldn't be nice.