In reality, this means that Java does not respect the principle of Uniform Access. That is, the client code for changing the field value (for example, obj.field = newValue ) is very different from the code for calling the installer (for example, obj.setField(newValue) ).
If you start with a public field and then decide that you really need a private member (for example, to add verification or change the basic implementation of a member), all of your client code will break. As a result, you need to use a setter, not a public field, if it is likely that you will need additional features provided by accessories. The end result is a lot of unnecessary code:
public class Person { private String _firstName; private String _lastName; public Person(String firstName, String lastName) { _firstName = firstName; _lastName = lastName; } public String getFirstName() { return _firstName; } public void setFirstName(String name) { _firstName = name; } public String getLastName() { return _lastName; } public void setLastName(String name) { _lastName = name; } }
Languages ββthat respect UAP, such as Scala , often use public fields instead of getters / seters. The above class in Scala, for example, writes:
class Person(var firstName: String, var lastName: String) // example client code: val p = new Person("John", "Smith"); p.lastName = "Brown";
If I decide that I need a check, I can replace this with:
class Person(firstName: String, lastName: String) private var _firstName = validate(firstName); private var _lastName = validate(lastName); // getters def firstName: String = _firstName def lastName: String = _lastName // setters def firstName_=(name: String): Unit = { _firstName = validate(name); } def lastName_=(name: String): Unit = { _lastName = validate(name); } // validation @throws(classOf[IllegalArgumentException]) private def validate(name: String): String = { // ... validation code ... name } } // and client code doesn't break! val p = new Person("John", "Smith"); p.lastName = "Brown";
source share