Xanthir wrote:So, like, Rust has traits, which classes can opt into. A trait describes some set of methods/etc that the class has to implement, and then you can use the trait in your type declarations. For example, the Error trait requires that you already implement the Debug and Display traits, and then description() and cause() methods. You can then write a function that operates on Errors generically, depending just on the properties guaranteed by the Error trait (compile-time enforced), and pass in any object you want so long as it derives Error.
This is a first-class handling of the same sort of thing that type erasure is a hack around, yes?
(Sorry if I'm sounding dumb or something; every single time Yakk has talked about type erasure and provided sample code, it goes straight over my head.)
I don't know how familiar you are with Java, but that sounds like how interfaces work. Interfaces are basically a list of methods that a class must implement (e.g. a class with the Runnable interface must have a run() method). You can then use the interface like you would any other class (e.g. function arguments, variables, etc.), except you can't create a new instance of it.
Type erasure, as used in Java, is used for generic classes. So, if you wanted a List of Foos, you don't have to create a FooList class specifically for containing Foos, nor do you have to use a List of Objects, and have to cast whatever you get out of it back to Foo. Instead, you create a List<Foo> that is treated at compile time like a List specifically for containing Foos (so you can only insert Foos into it and you only get Foos out of it), but at run-time it is really a List of Objects that happen to all be Foos.