4 ms·
It’s kind of embarrassing but I didn’t understand generics from my beginner CS course (taught in Java). It wasn’t actively tested on either. I only began to app
by bokwoon 6y ago
It’s kind of embarrassing but I didn’t understand generics from my beginner CS course (taught in Java). It wasn’t actively tested on either. I only began to appreciate it when I took an online MOOC in OCaml on a whim.
- kick 6y agoGenerics in Java were poorly-handled and almost universally considered to be a mistake.
- djsavvy 6y agoWhy is that? And how so?
- nitrogen 6y agoI'm not the OP, but look up "type erasure" for one criticism.
- lazulicurio 6y agoType erasure gets an unfairly bad rap. Yes, it makes reflection difficult sometimes. Yes, it doesn't play well with value types. But other than that, erasure is a very powerful concept.
- MereInterest 6y agoMy understanding is that the only value in type erasure is that it maintains compatibility with libraries compiled in ancient versions of Java. Are there language-level benefits to type erasure?
- lazulicurio 6y agoAbsolutely. Erasure lets you write code that's actually generic, instead of code that appears to be generic. For example, in C# IList<Foo> and IList<Bar> are two different interfaces that happen to have similar methods. Whereas in Java, List<Foo> and List<Bar> are the same interface. This means you can do things like this in Java: List<?> list = ... Object o = list.get(0); To do something similar in C# is significantly more effort. You either have to duplicate all of your interfaces (IList + IList<T>), use `dynamic`, or use reflection to compile delegates at runtime. A common complaint is "but erasure lets you add an integer to a list of strings". But as long as you follow PECS[1] rules you can avoid most of those situations. [1] Producer: extends. Consumer: super
- jdmichal 6y agoI don't think either of your points has anything to do with type erasure, and everything to do with allowing generics to take value types. This was an easy decision in Java, since it doesn't (yet?) allow user-defined value types. But C# has had `struct` since the beginning. C# creates one instance of a generic for all reference types. The general consideration in instantiating multiple versions is object size. All reference types are the same size, so not a concern. Value types, however, range wildly in size and so generally get their own specialized versions during code generation. The same choice effects the ability to wildcard. C# probably could implement wildcards over reference types, but it would feel inconsistent without value types. And, honestly, a good portion of wildcarding in my experience is to handwave away the compiler when you know what you're doing without reified types. Simply not an issue in C# -- its stronger guarantees around generic types means I can make that same code generic over the type I'm wildcarding in Java.
- lazulicurio 6y agoCode generation is definitely important to talk about, but that really wasn't the focus of my first example. Even if Foo and Bar were both reference types, the same reasoning would apply. In C#, you can do: class MyClass : IList<Foo>, IList<Bar> { ... } In Java, you can't do: class MyClass implements List<Foo>, List<Bar> { ... } I know this is commonly viewed as an annoying restriction, but, IMO, it's rather an indication that you're writing code that doesn't respect the contract of the generic interface. For example, what should the `Count` property return if you're implementing IList<T> twice? (C# wiggles around this with explicit interface implementations, but I think it's fair to argue that that's not a strictly superior approach to Java's).
- pjmlp 6y agoYes, Scala could not map their generics concepts to .NET due to reified generics and their developers gave up on Scala.NET.
- pjmlp 6y agoSay that to the Scala.NET folks.