top | item 8874761

(no title)

Proleps | 11 years ago

why not use:

  public final class Article{
    public final String title;
    public final String author;
    public final List<String> tags;
    public Article(String title, String author, List<String> tags) {
      this.title = title;
      this.author = author;
      this.tags = tags;
    }
  }
Getters don't seem very useful on an immutable object.

discuss

order

organsnyder|11 years ago

If you ever want to change the implementation of Article, you'd break anyone that was using that part of your API. If you use getters, you can change your implementation without breaking the consumers of your API.

For instance, let's say that you don't want to store the author's name as a string anymore, and want to store a reference to an Author object. If you have a getAuthor() method, you can change it from a simple getter to instead call author.getName(), preserving your public-facing API.

TheLoneWolfling|11 years ago

And this is one of the major reasons why Java is regarded as verbose. There's a simple solution (have the compiler transparently rewrite references to x.foo to x.getFoo / x.setFoo and transparently add getFoo/setFoo - the JVM inlines (trivial) getters and setters anyways) and yet Java, in the interests of "transparency", doesn't allow it.

And their justification fails. Sure, currently if you read x.foo you know that no code is being executed - but you never see x.foo because everything has getters and setters. So all it does in practice is make things (even) more verbose.

virmundi|11 years ago

So I think a fair question at this point is how often does that happen? To further inquire, how often does that happen in contexts that you don't control?

I'm sure that library/framework people need to worry about that. Most normal developers do not. For many cases Java objects like Article are just structs. They are static maps. Sure, in the example on the site there was a getTags that added some logic, but still, pretty much a struct.

Switching to either public accessor for mutable or immutable objects actually will stream line code. You might say that public mutators are bad; encapsulation and all that. For the most part little is actually gained in the majority of getter/setter code to necessitate their weight.

Heck, as per the JavaBean spec (a spec for making components to create drag and drop UIs by the way), you can't even have fluent APIs where the setter returns "this". It has to be void.

API stability has value. If you're a library, you probably want to do this just to be safe. But really for most imperative Java code it's just a lot of fluff for little value.

V-2|11 years ago

Besides, getters and setters are debuggable. They allow you for setting breakpoints, adding Log calls etc... Not so in case of fields.

It would be nice to have some syntax sugar for defining properties more tersely though, like in C#.

thescrewdriver|11 years ago

That's also one of the differences between Scala and Java. In Scala you have referential transparency, so you easily can switch between fields/properties and methods without changing the calling code.

Proleps|11 years ago

> If you ever want to change the implementation of Article, you'd break anyone that was using that part of your API. If you use getters, you can change your implementation without breaking the consumers of your API.

Then it wouldn't be immutable, if I can change the implementation I can also create a mutable version.

Edit example

  public class Article {
      private final String title;
      private final String author;
      private final List<String> tags;

      private Article(String title, String author, List<String> tags) {
          this.title = title;
          this.author = author;
          this.tags = tags;
      }

      public String getTitle() {
          return title;
      }

      public String getAuthor() {
          return author;
      }

      public List<String> getTags() {
          return tags;
      }
  }

  public class MutableArticle extends Article {
      private String title;
      private String author;
      private List<String> tags;

      public MutableArticle() {
          super(null, null, null);
      }

      public String getTitle() {
          return title;
      }

      public void setTitle(String title) {
          this.title = title;
      }

      public String getAuthor() {
          return author;
      }

      public void setAuthor(String author) {
          this.author = author;
      }

      public List<String> getTags() {
          return tags;
      }

      public void setTags(List<String> tags) {
          this.tags = tags;
      }

  }

thescrewdriver|11 years ago

Java code tends to follow the JavaBeans naming convention even when not implementing beans.

Scala version of your code:

    case class Article(title: String, author: String, tags: List[String])

V-2|11 years ago

But you can still modify elements of a final List (thereby modifying the Article object).

Properly implemented getTags should create a copy of tags so that fiddling with the returned value doesn't affect the object.