the instance of which is a LinkedHashMap. This method gets called from another method method2 which expects the values in the Map to be ordered. What would be the better practise in this case — keeping the method1 return type to be a Map or a concrete type of LinkedHashMap?
I am inching to go with changing it to LinkedHashMap but the pedantic me in wants to go the usual way and keep it Map
sorry read it the wrong way, i would keep it Map if your method1 does not care about other consumers and change it only to LinkedHashMap if it does, in your soecific case i would keep it Map
I am of the contrary opinion, because the method1 will only every be called from method2
well, then you are of the same opinion since you want your method to care about the consumers of its return type and explicitly state the concrete type :)
Haha! yes! Thanks for replying
I completely disagree with principle you proposed. If we follow it, then we can simply return "java.lang.Object" from all the methods everywhere. Why to stop at Map and not go higher on type hierarchy chain?
This is very simple, it's all based on encapsulation principle. Yes, that same encapsulation which you can read about on first pages of any OOP chapter. When you define a contract by deciding which type to return, you should answer two simple questions: - what is part of public contract - what are details of implementation In your case you should decide whether "ordered" quality of returned Map is important and is part of the contract, or it's only irrelevant details of implementations under the hood. In other words - will it make a difference if in the future you decide to change implementation of "method1" and will return unordered (HashMap) from the method1? If "ordering" is part of the contract, it should be stated in returned types. And it should not be if it's just details of implementation that may change without affecting the system. Based on your description, "ordering" is important part of the contract. And you can't return regular HashMap from the method without breaking things. Then it definitely should be stated in the contract, i.e. returned type.
yeah lets ignore the fact that there is a contract between the producer and the consumer... btw i didnt mentioned it because the person asking the question didnt give the impression that he wants go further up the ladder than the Map interface so next time please take this into account otherwise i could throw the very same argument against your explanation which is technically the same just for a wider audience
But how we can ignore it, when having a contract is the cornerstone of OOP? You always define a contract for callers when you draw the line between what is public, and what is private (i.e. details of implementation that may change). You can't just say "oh, let's ignore this". It's core feature of the language, and not only in java. There's nothing about "impression", these things are pretty strict and unambiguous. For the return type, the closest common supertype of all potentially possible returned objects is chosen. What's hard to predict is what can be those "all potentially possible returned objects". For example: ??? produceSomething() { // this can return String, Map, Object // closest common ancestor is Object, // this method should return Object or ??? produceSomething() { // this can return HashMap, any impl of NavigableMap, or ConcurrentHashMap // what's the closest common ancestor - Map // this method should return map And in the original question there was the case: ???? method1() { // this method can return only LinkedHashMap // >>> returning any other flavor of map here won't ever make sense for this method <<< // what's closes common ancestor - LinkedHashMap We propose completely different things. You suggested to return Map here. Why you decided to go exactly one level up the hierarchy? (Actually there could be good reasons for that - when there's interface over abstract calss one step up, in such case it may make sense). Why not 2 or 3 levels up? And what I suggest is completely different - I suggest to apply encapsulation and polymorphism here, and simple "closeset common ancestor" principle which is strict, repeatable and unambiguous unlike "don't care about contract, return 1 level up on type hierarchy" principle. How that can be "technically the same just for wider audience"?
Again, there's one simple example to demonstrate that returning just a Map here is wrong: class Service1Impl_1 { Map method1() { var result = new LinkedHashMap(); /// ...... return result; } } class Service1Impl_2 { Map method1() { var result = new HashMap(); // ....... // can this even make sense at all ? return result; } } class Service2 { private Service1 service1; void method2() { var map = service1.method1(); // we expect map here to be ordered } } This will not work when I switch Servcie1 implementations. If Impl2 could ever exist of course. And if I used LinkedHashMap as return type, will always work
Both of you are essentially providing the same solution to the problem
You do truly not get that i have never argued against you and was with my very first response in favour of the very same solution you proposed :)
Yep, I truly do not understand how "use encapsulation and polymorhpism to define strict contract" vs "do not care about contracts", and "use LinkedHashMap because ordering is part of the contract" vs "use Map" principles can be very same. But probably that's me missing something here, since already 2 people are saying that it's the same. Sometimes I can be blind as hell and miss some important point on the surface)) Anyway, hope that some of my thoughts and reasoning were helpful for someone in this chat.
Обсуждают сегодня