4 ms·
What's the "Java way" of accomplishing something like you'd represent with Union or Intersection types?
by ubercore 5y ago
What's the "Java way" of accomplishing something like you'd represent with Union or Intersection types?
- dljsjr 5y agoA common interface with all of the required functionality exposed as interface methods. A Java person would argue that if you have a function that takes an object that can be two totally disparate things with no shared functionality then that’s a code smell.
- taeric 5y agoApologies for forgetting I had posted this... :( My gut would be a visitor for the fully general case. Though, I would also accept that you are using the wrong language for the abstractions your are writing? My guess is it will depend on why you are needing/wanting one of those types. For a lot of plumbing code, these aren't as necessary as stipulated. Yes, there could be some duplication of code. But, especially in a microservice landscape, most of that duplication will be each service doing their version of whatever you are doing.
- programmer_dude 5y agoThere is none, without up or down casting. This is just some "guideline" that gets paraded from time to time (in OOP circles). On second thought, I am sure there's a "design pattern" for sum types out there. Why take the easy way out, am I right?
- deleted 5y ago[deleted]
- tomtheelder 5y agoProbably with a composite class I guess. So a union type of types A and B has members of types A and B, and a non-nullable flag to indicate which one this instance is. Intersection type is just the same thing without the flag. I don't write Java, though, just guessing.
- Someone 5y agoYou can also implement an union type as a sealed interface/abstract class with two classes that implement/extend it (https://openjdk.java.net/jeps/409 https://openjdk.java.net/jeps/409, https://www.baeldung.com/java-sealed-classes-interfaces https://www.baeldung.com/java-sealed-classes-interfaces)
- mumblemumble 5y agoIt's one option. It has the advantage of structurally limiting the types that can be used in that spot. It has the disadvantage (compared to true union types) of offering no static help beyond that. If you add a case, for example, you're 100% on your own to make sure that all code that interacts with the type is updated to handle the new case. Slip-ups will produce run-time errors rather than static ones. It's also rather tricky (and awkward) to set things up such that consumers are forced to check the case value before attempting to coerce it. All of this can be worked around with custom linter rules, but then that becomes its own maintenance burden. My preference is to try and invert things such that you can rely on dynamic dispatch and "tell, don't ask." That eliminates the need to coerce things at run-time in the first place.
- avita1 5y agoOther comments have linked newer language features that make it easy. But for years, the Java Way of handling discriminated unions was to use the visitor pattern [1]. It's very verbose, and is an insane amount of typing unless your IDE is doing the typing for you, but it has the compile time guarantees that forces each caller to handle every type without instanceof/Object. [1] https://dzone.com/articles/design-patterns-visitor https://dzone.com/articles/design-patterns-visitor