10 ms·
Nothing pollutes java source more than getters and setters. I can't believe this still isn't being address. Wish they'd move in the direction Groovy has in this
by rufugee 12y ago
Nothing pollutes java source more than getters and setters. I can't believe this still isn't being address. Wish they'd move in the direction Groovy has in this regard.
- evacchi 12y agoKotlin is pretty nice for that. Also, project lombok is nice for Java code generation. I wish it became more "standard"
- sgarlatm 12y ago+1 It is pretty astonishing they haven't done something about that. It doesn't seem like it should be a very hard language feature.
- exabrial 12y agoAmen. How about some language keywords like "readable" and "writeable"? public class Foo { public readable int canSeeeMeButCantChange; public writeable int cantReadMe; public int existingBehavior; } These are pretty simple changes to the compiler and verifier. You would make canSeeeMeButCantChange an invalid "left hand" variable in the compiler, and the verifier would have to check for any writes to the fields. cantReadMe would be an invalid right hand variable, and a similar check for the verifier. Any other public field behaves as normal.
- exabrial 12y agoThe other "Missing feature" is null safe ".". Other languages have it, but I don't know what the technical name is... basically: Integer val = some.other.chain.of.objects.value; In Java, this code has a huge potential for NullPointerExceptions. Instead a new operator (yes, I know) like: Integer val = some.?other.?chain.?of.?objects.?value; If any of the intermediate objects are null, the whole assignment becomes null. This could be done with a smarter compiler (easy way), or a new JVM bytecode (probably 'better' but not easy).
- necubi 12y agoThis is solved in a more general way in Java 8 via monadic optionals. The basic idea is to wrap your nullable objects in an Optional<T>, which then both forces you to deal with the possibility of the value being absent and gives you good tools for doing so. Your example, with Optional, looks like this: T obj = ...; Optional.of(obj).map(T::some).map(U::other).map(V::methods).getOrElse(null); Not quite as clean syntactically, but much more general, as the same operations can be applied to other monadic objects.
- sanderjd 12y agoThe sugar your parent proposed would still be nice and has precedent in other languages with option types. Swift has something very similar[0], and Rust is debating it[1]. Haskell's do-notation and Scala's for-comprehension are other solutions to the same general problem of conveniently using option types. It may be a good thing to only support that sort of convenience for option types and not for nulls, in order to further encourage their use. Although using nullable types is already pretty darn convenient! [0]: https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/OptionalChaining.html https://developer.apple.com/library/prerelease/ios/documenta... [1]: https://github.com/rust-lang/rfcs/pull/204 https://github.com/rust-lang/rfcs/pull/204
- rybosome 12y agoThis is kind of a pedantic distinction, but the behavior you've described is actually Functor behavior; I think Monads allow for Functor-like behavior as part of their definition (not sure, I'm neither a category theorist nor an experienced Haskeller), but their use is something a little bit different. Monads allow you to do two things: 1) Lift regular values into monadic ones in a generic way. Let's say that we have two Monads - Optional and List. There should be a way such that we can take a non-monadic value (the part that will go inside) and turn it into a Monad. So, assuming Monad is a Java-like abstract class, the following should be possible: Monad<String> m1 = Optional.lift("hello"); Monad<String> m2 = List.lift("hello"); 2) Flat-map, typically called bind in this context. Given a monad and a function that takes a value and returns a monad, we should have some way of combining the resulting monads if we were to map this function over the first monad's internal value. So for instance, given an optional string, and a function that takes a string and returns an optional int, we should have some way of combining the Optional<Optional<Integer>> into just an Optional<Integer>. So, in the following contrived example... // Returns a UTF8 string value from a database, may fail public Optional<String> getUtf8Name() { ... } // Returns the length of a String if it contains exclusively ascii characters public Optional<Integer> getAsciiLength(String str) { ... } ... you can compare the differences between it and the Functor's map: Optional<Integer> asciiLength = getUtf8Name().bind(getAsciiLength); Optional<Integer> otherAsciiLength = getUtf8Name().map(getAsciiLength).getOrElse(Optional.absent()); As it turns out, you can implement the Functor's map method in a generic way using lift and bind. public abstract class Monad<A> implements Functor<A> { /** * Implements Functor's map method. */ @Override public <B> Monad<B> map(Function<A, B> fn) { return this.bind( innerValue -> this.lift(fn.apply(innerValue)) ); } }
- mseebach 12y agoIs that not what final does? I'd be interested in seeing C#-like getters and setters. As long as they're just getting and setting, they're implied, but if you want to introduce a check or some other logic, you can do so without changing the signature of the class. Groovy does some of this, but it requires you to use the name of the field - ie. person.age will check for a getAge() method first, then fall back on the "age" field. I quite like that methods have verb-names, but I don't want to verb my fields.
- exabrial 12y agoYes, sort of like final... but different. I was thinking this is more for _public_ variables... so like internally, a class could modify it's own readable fields, but code external could read only.
- breischl 12y agoI do like how C# handled this, FWIW. public int MyProperty{ get; //public private set; //private-only setter } but obviously there are a lot of ways to skin that cat.
- lmm 12y agoMethods that actually do something should be verbs, but if it's just reading a property it should look like it's just reading a property. And having all the methods on a class start with get* is a pain for autocompletion.
- mseebach 12y agoHmm. I guess you're right. I dislike Groovy in other areas so it's not a path I've gone deep down. Especially for private APIs i Java I have actually tended to default to public final members, without verbs.
- memonkey 12y agoSorry to ask, but as a noob who just picked up Java, how do other languages address this issue? What's wrong with getters and setters?
- hugozap 12y agoFor c# just: public int Age{get;set;} no need to declare private variable, get or set methods.
- Tloewald 12y agoAnd you can replace it with a virtual property in the future (changing the underlying implementation) without breaking anything. And user code ends up simpler and more readable too: foo.baz += foo.bar; vs. foo.setBaz( foo.getBaz() + foo.getBar() );
- HanyouHottie 12y agoThat example reminds me of this recent post on The Old New Thing: http://blogs.msdn.com/b/oldnewthing/archive/2014/08/14/10549885.aspx http://blogs.msdn.com/b/oldnewthing/archive/2014/08/14/10549... Interesting behavior.
- Tloewald 12y agoOf course, setters don't protect you from this either.
- redtrackker 12y agoWhat's wrong with getters and setters? It's just redundant code. Most of the time developers don't actually need to override the basic get/set operation on a variable. Yet you have to write the get/set methods over and over. How do other languages address this issue? Scala does a good job. You don't need to actually write a get/set method. But if you wanted to modify getFoo() you would simply implement the method with your custom getter
- deleted 12y ago
- zo1 12y agoAnd making your instance variables public doesn't solve that for you?
- aikah 12y agoStates(properties) should never be public or it breaks encapsulation.That's why a language that allows a property to be a method under the hood is usefull, because the state is still encapsulated. State changes can have desirable side effects.If you expose an instance variable directly it's harder to encapsulate that. Of course there are exceptions. If you have a class that is meant to be only a parameter bag(in an rest API for instance),that's ok,imho.
- deleted 12y ago[deleted]
- deleted 12y ago[deleted]
- zo1 12y agoYour public facing methods/accessors are a sort of contract between a class, and whatever uses it. The contract basically says: "I will behave as you expect me to and as we agreed but only as long as you only interact with me in the predetermined(designed) ways that I allow you to"
- AnimalMuppet 12y agoHere's a class C with a variable v of type T. It's supposed to be something that the rest of the world can access. You can make it public. Or you can make it private, and write public T get_v() { return v; } So far, not much difference. Both let the world access the variable, and both break encapsulation by doing so. The difference comes when the class gets more complicated, and v changes. Now v might be null, whereas it never could be null before. But if it is, then what the rest of the world saw as v should now be some default value. So we can say: public T get_v() { if (v != null) return v; else return default_T; } and life goes on for everybody that was using v. But if all we had was a variable that everybody accesses, then all the users have to change. They either have to access the new getter or, worse, they each have to copy the logic to check for null. This is how the getter encapsulates the inner workings of the class, and why it's a really good thing. P.S.: How do I specify code formatting on HN?
- latchkey 12y agoThis doesn't solve the problem entirely or address your valid complaint, but it does do a good job of hiding it for now: http://projectlombok.org/features/GetterSetter.html http://projectlombok.org/features/GetterSetter.html
- cowardlydragon 12y agoGroovy replaces package-scoped variables with private vars and autogen'd getter/setters. So much nicer.
- bollockitis 12y agoIt isn't perfect, but Lombok[1] helps with this. It uses annotations to automatically generate getters and setters. The downside, of course, it yet another dependency and more annotations. [1]: http://projectlombok.org/features/GetterSetter.html http://projectlombok.org/features/GetterSetter.html
- evacchi 12y agoYou can setup your build process to "delombok" your sources, so that the dependency would only be compile-time (which is pretty neat). Also, Lombok has @Data http://projectlombok.org/features/Data.html http://projectlombok.org/features/Data.html
- maherbeg 12y agoWhat's even better is @Value with @Builder :) Immutability is the best. http://projectlombok.org/features/Value.html http://projectlombok.org/features/Value.html http://projectlombok.org/features/experimental/Builder.html http://projectlombok.org/features/experimental/Builder.html
- noblethrasher 12y agoI admire Java for the fact that it is significantly more painful to write mutable rather than immutable classes. I love C#, but I do wish that setters weren't so easy to define (and that classes were sealed by default, and that fields were read-only, and that all extant warnings would become errors, etc.).
- patrickmay 12y agoI agree 100%, but the problem is the culture that has grown up around Java. The whole Bean concept encourages violation of encapsulation. IDEs provide automatic generation of accessors and mutators. Many Java programmers have been trained to expect them. At this point, encouraging good OO practice is shouting against the tide. That being said, I still make my classes immutable unless there is a damn good reason not to.
- Consultant32452 12y agoIn Java culture immutable generally means private final member with only a getter and no setter. I would argue that this is good OO design as the purpose of OO design is to protect your interface from future design changes. If you need to change your accessor, you already have one. If the member needs to be mutable at a later date you need only remove the final keyword and potentially add a setter. The interface remains backwards compatible.
- patrickmay 12y agoI disagree. If you require an accessor to actual internal state, you should rethink your dependencies and reassign some behaviors. Accessors should be rare, mutators almost non-existent.
- bpodgursky 12y agoNothing pollutes java source more than code which REQUIRES setter methods for functionality. If you have classes which require constant mutable access to internal state, your design is probably flawed.
- unclebucknasty 12y ago>If you have classes which require constant mutable access to internal state, your design is probably flawed. How do you account for value objects in that statement? Are you saying there should be no such thing?
- wtetzner 12y agoThere's no reason value objects need to be mutable. In fact, they shouldn't be mutable. They're just data. Why would you need to mutate them?
- unclebucknasty 12y agoWell, in the strictest since, I suppose a "value object" is technically one that is immutable by definition. So, to your point, I should clarify that here I'm instead speaking more loosely of an object that is chiefly comprised of data elements vs. behaviors. So, a common use case might be loading data from a DB, changing several fields, then writing updates back to the DB.
- ryanobjc 12y agoIt is addressed by better design. First off, it's important to know the difference between value types and objects. For a value type, public final fields are good. They are set in the constructor once, and can only be read, and can't change. Getters are pointless, and my code does not have them. If you want them for a reason, then intellij does an amazing job fixing that. Objects encapsulate mutable state, and getFoo() and setFoo() are inappropriate methods to have. They should be things that affect the behavior of the object, not simple setters and getters. The big issue is that a lot of java was created when we still hadn't figured out how to properly do Object Oriented Programming. But we know now (well - some of us), and there is nothing in Java that prevents you from doing it well.
- rbanffy 12y ago> It is addressed by better design. This! A lot of the horrible Java you see around is nothing but an artifact of mindlessly applying patterns to constructs that don't need them. > a lot of java was created when we still hadn't figured out how to properly do Object Oriented Programming. Which is quite unforgivable, considering Smalltalk has been around since the early 80's.
- spopejoy 12y agoMy problem is I don't think there's any agreement what Object Oriented Programming is and isn't, so it's pretty hard to "properly do it". Let's see. OOP generally involves "objects", ie structs or records with visibility controls on fields, sporting "methods," ie functions with a magic/hidden this/self argument. This alone doesn't buy you much, and in fact is quite inflexible when compared to good old ADTs, so let's hope there's more to it. OOP does not mean "all methods are defined within the class declaration/file" a la Java, plenty of OOPLs allow external method definition. So it doesn't mean "well in OOP I always know the behavior of my class" when you have friend functions etc. OOP might mean "abstract classes" ie virtual methods. This leads us to inheritance, which is a) not confined to OOP and b) widely criticized. Remember that inheritance != polymorphism, c.f. Visual Basic for instance (at least VB5. Showing my age...). In practice, OOP usually invokes a great-chain-of-being-like hierarchy descending from Object, but again this is not universal. OOP generally means "polymorphism", but the mechanisms vary widely. OOP's "Classic" inheritance-driven polymorphism is probably the worst way to do it, good for quick code-reuse and that's about it. "Interfaces"/pure virtual classes are a design pattern on top of abstract classes, better expressed as mixins or type-classes. OOP generally implies strong typing but not always (python). OOP typing is quite clunky, especially in "noun-oriented" Java. You can make an argument that the rise of DI frameworks is in response to having impoverished type systems. My semi-rant here is because people say things like "do it this way, it's good OOP" without there being any agreement about whether we're discussing polymorphism, inheritance, encapsulation, factoring, normalization, or design patterns that are largely a response to the confusion. On the other hand we have folks like the clojure crowd bagging on OOP using similarly vague concepts like "OOP means stateful objects/side effects" ...
- wyager 12y agoNot exactly comparable (because everything is immutable), but Haskell has sort of a cool approach to setting and getting fields. Let's say you have data Point = Point {x :: Int, y :: Int} If you have a Point object called "point", you can get x by doing x_coord = x point If you want to create a new Point with x set to 5, you can do point' = point {x = 5}
- vishbar 12y agoF# has a similar concept via the with statement. To use your example: type point = { x: int; y:int} let z = {x = 5; y = 10} let y = {z with x = 17}
- virtualwhys 12y agoInteresting, Scala equivalent is: case class Point(x: Int, y: Int) val p1 = Point(5,10) val p2 = p1.copy(x=17) How does F# handle nested data types? In Scala if you want to copy a case class of a case class (of a case class ...) it can get boilerplate-y as you have to copy outside-in through each property a la: x.copy(acase.copy(bcase.copy(cprop=1)))
- LoneWolf 12y agoWhy not just declaring the fields public and access them directly? Is there anything I am missing?
- Terr_ 12y agoWhat if you only want a getter? The `final` keyword is too restrictive. Also, it breaks encapsulation, because your internal storage should be changeable without ruining your external surface area.
- pje 12y agoburn your getters
- thescrewdriver 12y ago> Nothing pollutes java source more than getters and setters. I can't believe this still isn't being address. We ran out of patience and switched to Scala. Never been happier :)
- andima 12y agothat's not really because of the language, but mostly because of frameworks and patterns available for the language (Java Beans, reflection-oriented frameworks and so on). Often, getters and setters are more an habit than a need. A while ago I wrote against that: http://www.refactoringideas.com/getters-and-setters-gone-wrong/ http://www.refactoringideas.com/getters-and-setters-gone-wro...
- benjiweber 12y agoYou can always do something like this http://benjiweber.co.uk/blog/2014/03/20/c-style-properties-in-java/ http://benjiweber.co.uk/blog/2014/03/20/c-style-properties-i... Although I prefer not using getters & setters at all.
- spektom 12y agoIf there's a getter and a setter for a class field, you can just make it public.
- ossreality 12y agowhomp whomp. not really.
- TheLoneWolfling 12y agoThe problem is that in Java at least, you cannot. At least if it will be ever used by code beyond your control. Because then you'll never be able to add a getter or setter later without breaking people's code. Java is frustrating in that regard. As it should be able to deal with automatically invoking getters and setters when needed (it already inlines getters and setters at runtime, this is "just" the reverse), but it's a language decision that it doesn't. As an additional bonus, this would help reduce the (legendary) verbosity of Java. a.b += c.d is much easier to read than a.setB(a.getB() + c.getD()). And don't get me started on Java's generics or lack of operator overloading...
- iSnow 12y agoYou can always add Project Lombok as a dependency and the issue is gone. I know it is a third-party library but there's nothing bad about that.
- deleted 12y ago[deleted]
- eneveu 12y agoI'd use immutable value classes with AutoValue: https://github.com/google/auto/tree/master/value https://github.com/google/auto/tree/master/value . It's developed by the googlers behind the awesome Guava library.
- mslot 12y agoThen don't use getters and setters... A lot of complaints people have about Java seem to be about the way in which they choose to write Java. My somewhat unorthodox rules for writing Java: 1. Don't use private. No reason to restrict yourself or others, and do extra typing. Friendly is a perfectly good default. 2. Don't use reflection. Reflection is only useful for making frameworks. Frameworks don't reduce the complexity of the problem you're trying to solve. Don't use them. 3. Don't use getters/setters. Sometimes they make sense for updating a cached value, or using a different underlying representation, but in general it's unnecessary clutter. If you still want them (e.g., for code style reasons), just generate them. 4. Don't use other people's code (tongue-in-cheek). If you use third-party libraries, consider wrapping them in your own interfaces as needed. This makes it easy to change the implementation and perform tests. It's not much effort, since you'll rarely use more than a limited subset of the functionality offered by the library. If you need a large subset, then just use the library directly. 5. Use final. Immutability makes programs simpler, more efficient, and inherently thread-safe. 6. Consider writing bean classes as follows. It's simple, efficient, thread-safe, and has a clean syntax (item.name): public class Item { public final int id; public final String name; public Item(int id, String name) { this.id = id; this.name = name; } } 7. Use an IDE, refactor, find references, generate code. It's easy to changes names and styles later, so just focus on important things like performance and reliabiltiy. 8. Keep improving the way you write your code, don't listen to the crowd.