2

I'm making a Card class on Java, and I want it to be as idiomatic as possible. Should I encapsulate all the fields making them private and providing getters as following:

    public class Card implements Comparable<Card> {
        private char suit;
        private String name;
        private int value;

        public Card(char suit, String name, int value) {
            this.suit = suit;
            this.name = name;
            this.value = value;
        }

        public char getSuit() {
            return suit;
        }

        public String getName() {
            return name;
        }

        public int getValue() {
            return value;
        }


        public String toString() {
            return name + " of " + suit;
        }

        @Override
        public int compareTo(Card card) {
            return Integer.compare(value, card.value);
        }

    }

Or since any of the fields are not going to be modified, should make public and final all the fields:

    public class Card implements Comparable<Card> {
        public final char suit;
        public final String name;
        public final int value;

        public Card(char suit, String name, int value) {
            this.suit = suit;
            this.name = name;
            this.value = value;
        }

        public String toString() {
            return name + " of " + suit;
        }

        @Override
        public int compareTo(Card card) {
            return Integer.compare(value, card.value);
        }

    }

I'm reading Clean Code on the chapter of Data Structures vs OO classes, and I do not know what approach should I take in this case. Thanks in advance!

EDIT: This class is part of a BlackJack I'm developing, and I need to access the fields from another classes.

EDIT: This question has been put on hold, but, where does this question should be posted then? Should I move it to Code Review? I'm truly interested in knowing the opinions of more experienced programmers on this subject, but I want to post it on the right site

Davichete
  • 415
  • 7
  • 14
  • I'd make them all private and final and give each one a getter. – duffymo Sep 03 '19 at 12:39
  • Would not really make sense to make them public _and_ final if they cannot be modified no? That would be exposing them outside the class unnecessarily. – Nexevis Sep 03 '19 at 12:42
  • @Nexevis This class is part of a BlackJack that I'm developing, and I need to access the fields from another classes – Davichete Sep 03 '19 at 12:43
  • @Davichete But making them public allows them to accessed for modification _and_ reading, one of the points of making them private is that you can take away the privilege to `set` them if you want to, and only leave the `get`. With a public field you cannot remove `set`. – Nexevis Sep 03 '19 at 12:44
  • @Nexevis they're immutable objects in the second example. – Kayaman Sep 03 '19 at 12:47
  • @Nexevis How can you modify a `final` field? If I understood the final modifier, making a field final prevents the user from modifing it – Davichete Sep 03 '19 at 12:47
  • @Davichete @Kayaman I don't mean you can _actually_ modify them, I mean the intent of making them public. To me if you are making them final with the intent to not let them `set` the variable, you might as well make them private and final instead. Maybe it is just my opinion but `public final` seems contradictory. – Nexevis Sep 03 '19 at 12:49
  • @Nexevis but what is the difference between accesing them by a getter or by a field?, both expose the same information, the only difference I see is that the getter solution is slower – Davichete Sep 03 '19 at 12:52
  • Should have been closed as a duplicate of https://stackoverflow.com/questions/1568091/why-use-getters-and-setters-accessors – Andrew Tobilko Sep 03 '19 at 12:57
  • @Davichete I always vote to reopen such questions: Unfortunately, yours is a duplicate of https://stackoverflow.com/questions/1568091/why-use-getters-and-setters-accessors because it boils down to "why should I use getters" – Andrew Tobilko Sep 03 '19 at 12:59
  • @Andrew I do not think It's the same question, I focus my question on why, even when both (giving getters or makiing the fields `public final`) expose the same information, should I use one or another. I think it is not them same asking about wheter or not should I use getters or `public final` or asking about getters *and* setters or `public` fields. Since the second one change the behaviour, the first one not, it exposes the same – Davichete Sep 03 '19 at 13:24
  • @Davichete The Q&A Andrew linked to attempts to explain the "why". Whether or not you agree with the reasoning is different; there's also many arguments in the linked Q&A for both approaches. That said, I find that in Java it is very rare to see a publicly exposed _mutable_ field. If a field is public it is typically a constant (i.e. `public static final `). I have, however, seen mutable fields exposed as `protected` in order to allow subclasses to use them. – Slaw Sep 03 '19 at 14:05
  • @Slaw Correct me if I'm wrong, but fields marked as `public final` are inmutable, since you cannot change the value that contains. – Davichete Sep 03 '19 at 14:15
  • 1
    Yes, a `public final` field won't be mutable. Though note that only applies to the reference; it won't prevent a mutable object being stored in the field from being mutated. But again, in my experience using getters/setters is the idiomatic way of doing things in Java. – Slaw Sep 03 '19 at 16:10

1 Answers1

0

In theory, when you design OOP solutions, you must provide least priviledge wherever possible. Therefore, your first approach is way to go. But, I would rather implement the hashCode() to make it more clear about the uniqueness of a Card.

What you are trying to implement is called as immutable objects

Jude Niroshan
  • 4,280
  • 8
  • 40
  • 62
  • But, what priviledge am I giving with `public final` field that I don't give with the getter? It expose the same information, doesn't it? The only difference I can see is the readibility and the performance, making it public final is faster than the getter. Correct me if I'm missing something please – Davichete Sep 03 '19 at 13:44
  • You shouldn't make `public final` as it makes the attributes available through the entire application. Because encapsulation is one of the key principles of OOP. If you strictly want to make sure that attributes are not modified, just implement your `Card` to be **immutable** objects. [https://docs.oracle.com/javase/tutorial/essential/concurrency/immutable.html](https://docs.oracle.com/javase/tutorial/essential/concurrency/immutable.html) – Jude Niroshan Sep 03 '19 at 13:52
  • Isn´t a class with all fields `final` inmutable? You cannot modify anything. A public getter is also available through the entire application, and it gives the same information that the `public final` field. Both ways make the attributes unmodifiable. I still see no difference between one way or another – Davichete Sep 03 '19 at 13:56
  • I'm not going to steal his answer: https://stackoverflow.com/a/34087790/4506140 I hope now you can understand the difference in usage – Jude Niroshan Sep 03 '19 at 14:09
  • I cannot figure out a way of mutating, any of the fields of that class since all types involved (char, int, String) are inmutable. Is there any way that you can mutate any of them, even when are `final`? If so, please let me know. I understand the difference between `final` and inmutability, but I think in this case it is not the point – Davichete Sep 03 '19 at 14:20