3 ms·
> For me the main point is (runtime) polymorphism. E.g. you have a function that takes a general type, and you can pass multiple specific types and it will do t
by mrkeen 3y ago
> For me the main point is (runtime) polymorphism. E.g. you have a function that takes a general type, and you can pass multiple specific types and it will do the right thing.
The runtime part is what I dislike. If I have a fruit which is an apple or a banana, I can't pass that to a method expecting an apple or banana. It can only be passed as a fruit.
> And if you want to avoid huge if-else statements, you should put the code for the special cases in the classes, not in each function that operates on them.
This is common OO wisdom that I strongly disagree with. For example, in my program I have a few types (Application, Abstraction, Variable, etc.), and a lot of transformations to perform on those types (TypeCheck, AnfConvert, ClosureConvert, LambdaLift, etc.).
I prefer to have all the type-checking code inside the TypeCheck module, and all the closure-converting code inside the ClosureConvert module. I'd take the "huge if-else" statements inside TypeCheck rather than scatter typechecking across all my datatypes.
- rtz121 3y ago> If I have a fruit which is an apple or a banana, I can't pass that to a method expecting an apple or banana. It can only be passed as a fruit. You can by overriding the method on apple or banana. If your method is on some other object, then yes, you cannot do this unless your programming language supports multiple dispatch.
- zbentley 3y ago> I prefer to have all the type-checking code inside the TypeCheck module There are ways to have your cake and eat it too, here, at least in some languages and patterns. For example, in Go you could define "CheckType" as part of the interface contract, but group all implementors' versions of that method in the same file, calling out to nearby private helper functions for common logic. Ruby's open classes and Rust's multiple "impl" blocks can also achieve similar behavior. And yeah, sure, some folks will respond with "but go isn't OO", but that's silly. Modelling polymorphic behavior across different data-bearing objects which can be addressed as implementations of the same abstract type quacks, very loudly, like a duck in this case.
- Capricorn2481 3y ago> And yeah, sure, some folks will respond with "but go isn't OO", but that's silly. Modelling polymorphic behavior across different data-bearing objects which can be addressed as implementations of the same abstract type quacks, very loudly, like a duck in this case. It's less "this is not OO" and more this is not inheritance, which is why a lot of people are saying you can find more elegant solutions (like this) rather than use inheritance for no clear benefit.
- kaba0 3y ago> The runtime part is what I dislike. If I have a fruit which is an apple or a banana, I can't pass that to a method expecting an apple or banana. It can only be passed as a fruit. Heh? An apple is a fruit, you can pass it to any place expecting the former. Like, this is Liskov’s substitution’s one half. With generics, you can be even more specific (co/in/contra-variance).
- cornstalks 3y agoI think GP is talking about something like this: Fruit* fruit = new Apple(); ConsumeApple(fruit); // Doesn't work; requires Apple* fruit = new Banana(); ConsumeBanana(fruit); // Doesn't work; requires Banana* ConsumeFruit(fruit); // Okay, function signature is void(Fruit*)
- sfn42 3y agoBut why would you want to be able to pass an apple to a function expecting a banana? Doesn't even make sense, the whole point is that the type system forces you to consider this stuff. If OP wanted to be allowed to do whatever and just have the software fail at runtime, JS is right there.
- mrkeen 3y ago> But why would you want to be able to pass an apple to a function expecting a banana? I would never. I know that I'm holding a banana, I want to pass it to a method that receives a banana. But what I can't do is put my banana through a rotateFruit function first, because then Java will forget that it's a banana and start treating it as a fruit.
- kaba0 3y agoJava has generic functions since forever, something like `<T extends Fruit> T rotateFruit(T fruit)` would return your banana typed object just fine.