А давай те ка по быстрому разберемся, что такое модификаторы доступа в java (public private protected) и зачем они нужны?
Одним из принципов объектно ориентированной технологии программирования является принцип инкапсуляции. Что он из себя представляет? А тут все просто. Суть в том, что каждый объект объединяет в себе данные и методы работы с этими данными, и скрывает особенности реализации от конечного пользователя. Возьмем объект из реальной жизни, например «автомобиль». У этого объекта есть определенные данные например количество топлива в баке, тип двигателя, количество колес, расход топлива, тип тормозной системы и т.д. И есть методы — например завести двигатель, поехать, остановиться. Достаточно много людей понятия не имеет как именно функционирует тот или иной механизм в их автомобиле, однако это вовсе не мешает им ездить каждый день на работу. Дело в том, что у автомобилей есть стандартный интерфейс: педали тормоза, газа, сцепления, руль, рычаг управления коробкой передач (ну если не трогать машины с автоматической коробкой, там все еще проще 🙂 ). Так вот получается что автомобиль инкапсулирует огромное количество данных и методов, но мы можем пользоваться им не вдаваясь в особенности реализации его конструкции.
То же самое имеет место и в объектно-ориентированном программировании. например мы создаем класс линия:
public class line { public float x1,y1,x2,y2; public line(float x1, float y1, float x2, float y2) { this.x1=x1; this.y1=y1; this.x2=x2; this.y2=y2; } }
У нашей линии имеются координаты первой точки и координаты второй точки. Это (x1,y1) и (x2,y2). И имеется конструктор. И то и другое имеет модификатор доступа public. Это значит, что в любом другом классе или объекте мы можем написать такой код:
line l = new line(1,1,2,2); l.x1=3;
То есть и поля и методы класса доступны для всех других объектов и классов. Теперь добавим к нашему классу свойство «длина». Получаем такой вот класс:
public class line { public float x1,y1,x2,y2; public float length; public line(float x1, float y1, float x2, float y2) { this.x1=x1; this.y1=y1; this.x2=x2; this.y2=y2; calculateLength(); } public void calculateLength() { length=(float) Math.sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1)); } }
Здесь уже есть метод для расчета длины и он вызывается в конце конструктора. То есть длина рассчитывается автоматически для каждой новой линии. Однако что произойдет, если мы с Вами из другого класса напрямую изменим какую либо из координат:
line l = new line(1,1,2,2); l.x1=3;
Получится что координаты концов отрезка изменились, а его длина осталась прежней. Вот в таких-то ситуациях и нужно использовать модификаторы доступа. перепишем наш класс по новой. Теперь уже спрячем поля класса модификатором private и обеспечим к ним доступ через специальные методы доступа (еще такие методы называются аксессорами), так чтобы пользователь класса не мог изменить поля напрямую, а только с помощью специального метода.
package ru.davidmd.testapp; public class line { private float x1,y1,x2,y2; private float length; public line(float x1, float y1, float x2, float y2) { this.x1=x1; this.y1=y1; this.x2=x2; this.y2=y2; calculateLength(); } private void calculateLength() { length=(float) Math.sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1)); } public void setX1(float x1) { this.x1 = x1; calculateLength(); } public void setY1(float y1) { this.y1 = y1; calculateLength(); } public void setX2(float x2) { this.x2 = x2; calculateLength(); } public void setY2(float y2) { this.y2 = y2; calculateLength(); } public float getLength() { return length; } }
Теперь если мы вызовем метод setX1(10) то в этом методе длина отрезка пересчитается автоматически, а значит всегда будет актуальна. А поля которые скрыты за модификатором доступа private будут просто недоступны из других классов и объектов.
Ну с этим вроде понятно, а зачем же нам нужен модификатор protected? А давайте на основе нашего класса создадим линию которая умеет не только изменять свою длину, но и выводить на экран координаты своих концов. Например так:
public class printableLine extends line { public printableLine(float x1, float y1, float x2, float y2) { super(x1, y1, x2, y2); } public void print() { System.out.println("point 1 - ("+this.x1+","+this.y1+""); System.out.println("point 1 - ("+this.x2+","+this.y2+""); } }
Оп-па! А вот тут мы сталкиваемся с ошибочкой! Ведь поля класса родителя скрыты от нас, и значит распечатать их мы не можем! Но выход, как говорится, всегда есть. Достаточно просто поменять для полей x1, y1, x2, y2 модификатор доступа private на protected и мы получим доступ к этим полям из всех классов-потомков, однако для других классов они останутся недоступны!
Наконец-то!
Спасибо за доступное разъяснение!
Да незачто! Надеюсь кому-то полезно!
И от меня спасибо!
Вот почему в книгах так доступно не объясняют? 🙂
Ну не скажи… Есть очень много хороших книг, в которых все очень понятно и доходчиво объясняют.
В общем доброму челу за всегда спасибо, но IMHO: это среда программирования. И директивы нужно не просто знать, а понимать, каким способом они приведут к результату….
(Digesta): между низким уровнем программирования машин и высоким уровнем программирования в мозгу человека, находится то, (что человек больше всего в себе не любит…)
ЗЫ: предложение построено правильно…
Огромное спасибо!
Отличная статья, но для совсем начинающих было бы неплохо прокомментировать строки кода..
Спасибо, для начинающих действительно очень полезно. Но также часто даже в простых примерах встречаются такие слова как «@Override» , «void» , «super.» , «Bundle». И для новичков (я) не всегда понятны эти зарезервированные слова. Хотелось бы побольше статей для лучшего понимания синтаксиса Java под android.
PS: пару дней изучаю, сорри если банально.
вот тутта немного есть по теме
Поправьте опечатку:
System.out.println(«point 1 — («+this.x1+»,»+this.y1+»»);
System.out.println(«point 1 — («+this.x2+»,»+this.y2+»»);
вроде должно быть («point 1 — … и («point 2 — …
Когда поправите удалите комментарий.
Спасибо за объяснения.
Отличное разъяснение. Спасибо.
Очень полезно, спасибо Вам. Мне кажется что стоит еще обратить внимание на то, что сначала мы могли напрямую изменить public float length(то есть в обход вычислению длины), а когда мы уже это поле объявим как private, тогда не сможем его изменить .
То есть в 1-м варианте мы могли высчитать длину через метод а потом сразу напрямую изменить поле length(так как оно public).
Продолжай писать статьи по Java и Android! Это будет классно!
Спасибо!
Незачто!
Private считаю не совсем корректно объяснено,ведь никто не будет писать отдельный класс что бы выводить на экран цифры из другого класса,проще метод вывода сделать там,либо на худой конец метод по получению этих переменных,из класса.И хотелось бы дополнение по поводу конструкторов и методов в этой статье,не совсем понятно как их отличать и зачем нужен конструктор,почему нельзя переменными в класс передать