В "Normal
" (в этом нет ничего "нормального"), это совершенно правильный код:
public static void main(String args[]) {
Normal normal = new Normal();
normal.name = "suhail gupta";
System.out.println( "My name is : " + normal.name );
}
Ваш интерфейс теперь включает в себя значение String
, называемоеname
.Пользователи ожидают, что смогут установить его, используя синтаксис VarName.name или VarName.setName.Пользователи ожидают, что смогут получить его либо с помощью VarName.name или VarName.getName;
Например, это допустимо в "Normal
":
public static void main(String args[]) {
Normal normal = new Normal();
normal.name = null;
String name = normal.name;
System.out.println( "My name is : " + name );
}
Теперь, возможно,ты подумаешь "ну и что?"Представьте, что значение переменной, равное null, отделено от фактической печати (где происходит ошибка) 30 файлами.Будет очень трудно узнать, кто облажался со значением этой переменной.И ничего вы не можете сделать, чтобы пользователь не испортил его.
Теперь, если вы реализовали setName
следующим образом:
public String setName(String newName) {
assert newName;
name = newName ;
return name ;
}
Тогда,ошибка происходит немедленно , когда пользователь делает что-то не так.Пользователь попытался установить значение NULL, которое не может быть NULL, поэтому ошибка.У вас есть стек вызовов, который показывает, где произошла ошибка, и это намного легче отладить.
Конечно, это не помогает, потому что пользователь "Normal
" не должен используйте setName
.Они могут свободно тыкать в name
напрямую.
Хотя это технически может быть инкапсуляция, насколько я понимаю, если пользователь может легко и тривиально разрушить ее, это не инкапсуляция.Если нет защиты, нет инкапсуляции.
Когда они говорят, что Unencapsulated означает «неизменяемый», как он неизменен здесь?
Хорошо, допустим, вы даете мнебиблиотека, содержащая Normal
.Я буду использовать это каким-то образом.Возможно, у меня есть Normal
экземпляра, разбросанных по 50 файлам.Они все устанавливаются напрямую и получают имя по name
, а не по методам доступа.Это совершенно законно, потому что вы сделали это public
.
Теперь, по любой причине, вы решаете, что не хотите хранить имя в строке.Может быть, вам нужно иметь имя и фамилию.Итак, допустим, что следующая версия вашей библиотеки имеет следующее определение:
public class Normal
{
public string firstName;
public string lastName;
public String getName()
{
return firstName + " " + lastName;
}
public String setName(String newName)
{
//parse newName into a first and last name.
...
firstName = newFirstName;
lastName = newLastName;
return getName();
}
}
Чего не хватает?public String name;
Это больше не доступно, потому что теперь у вас есть имя и фамилия.Обратите внимание, что два метода доступа вообще не изменились .
Когда я обновлюсь до новой версии вашей библиотеки, вы просто сломаете весь мой код ,Мне не нравится, когда мой код нарушается просто потому, что вы решили изменить способ хранения данных в своем классе.Теперь я никогда не буду использовать то, что вы делаете снова, потому что вы не можете даже поддерживать свой интерфейс согласованным от одной версии к другой.
И если бы вы только что сделали все правильно, ничего бы не случилось.