Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Java: Общие вопросы > protected в jdk1.6.0_01


Автор: nornad 26.6.2007, 03:24
Или я совсем старый стал и ничего не смыслю в модификаторах доступа, или в указанной ждк баг.
Вот пример:
Код

public class Protected
{
    protected boolean isTrue = false;
    protected int id = 10;
}

Код

public class ProtectedTest
{
    public ProtectedTest() {
        Protected prot = new Protected();
        System.out.println("Why there is no error? ... " + prot.isTrue);
        System.out.println("Why there is no error? ... " + prot.id);
    }

    public static void main( String[] args ) {
        new ProtectedTest();
    }
}

Вопрос: как это может работать?

Добавлено через 8 минут и 47 секунд
М-да... прошу прощения, я действительно ничего не понимаю в модификаторах доступа.
Нашёл тут в довольно старенькой книжке (точнее, в заметках, сделанных по книжке), что
Код

protected виден всем в пределах пакета

Имхо, несколько странное поведение для защищённых полей и методов, но "описанный баг - уже не баг, а фича". smile 

P.S. Просьба к модераторам: не удаляйте тему. Думаю, найдутся и другие "ничего не смыслящие". smile

Автор: jsa 26.6.2007, 05:11
хм... очень интересно, не знал таких подробностей, поэтому порылся на java.sun.com и вот что нашел
http://java.sun.com/docs/books/tutorial/java/javaOO/accesscontrol.html

Автор: Ulysses4j 26.6.2007, 06:00
Цитата(jsa @ 26.6.2007,  06:11)
хм... очень интересно, не знал таких подробностей, поэтому порылся на java.sun.com и вот что нашел
http://java.sun.com/docs/books/tutorial/java/javaOO/accesscontrol.html

Давайте не будем томить народ, там речено:
Цитата
The protected modifier specifies that the member can only be accessed within its own package (as with package-private) and, in addition, by a subclass of its class in another package.

Лично мне такое не нравится - Delphi вспоминается...

Автор: nerezus 26.6.2007, 06:00
Цитата

protected виден всем в пределах пакета
 
Собственно это как бы прописная истина ;)

И еще: если сабж без модификатора, то ведет он себя именно так, как ты хочешь, чтобы вел себя protected ;)

Автор: Ulysses4j 26.6.2007, 06:00
Цитата(nornad @  26.6.2007,  04:24 Найти цитируемый пост)
Думаю, найдутся и другие "ничего не смыслящие".

+1

Добавлено через 4 минуты и 52 секунды
Цитата(nerezus @  26.6.2007,  07:00 Найти цитируемый пост)
если сабж без модификатора, то ведет он себя именно так, как ты хочешь, чтобы вел себя protected ;)

Хотите сказать, что package-private и protected это одно и то же? Сомневаюсь. Если подкласс данного класса находится в другом пакете, то protected-члены базового ему будут видны, а package-private базового - нет.

Автор: nornad 26.6.2007, 07:15
Цитата(nerezus @  26.6.2007,  09:00 Найти цитируемый пост)
И еще: если сабж без модификатора, то ведет он себя именно так, как ты хочешь, чтобы вел себя protected

Не скажи. Судя по информации на офсайте поле без модификатора ведёт себя не так, как protected в том же с++. Смотрим в табличку и видим, что такое поле видно в пределах пакета, но не будет видимым классу-потомку, который лежит в другом пакете. "Стандартный" же protected наоборот подразумевает видимость потомкам, а не пакету.

Автор: fixxer 26.6.2007, 09:24
Вся эта котовасия происходит от желания _четко_ разделить иерархию доступа, то есть, чтобы одна полностью включала другой.
public
protected
package
private

И вследствие этого к пакетам следует относиться внимательнее, помня, что это не только средство модульной декомпозиции, но и средство инкапсуляции.

Автор: LSD 26.6.2007, 09:53
Цитата(nornad @  26.6.2007,  08:15 Найти цитируемый пост)
"Стандартный" же protected наоборот подразумевает видимость потомкам, а не пакету.

В Java он ведет себя именно так как описано выше, с самой первой версии. О причинах fixxer уже написал.

Автор: nornad 28.6.2007, 19:25
М-да... что-то я всё же заглючил. protected ведёт себя почти так, как я и понимал. Так же как и no modifier.
Единственный момент, которого я не знал - это, что protected виден и всем внутри пакета.

Автор: progdog 30.6.2007, 08:47
В книжке "Секреты программирования для Internet для Java" еще по jre 1.0 было написано, что тогда во всяком случае был еще один модификатор. Цитата с книжки:
Цитата

Модификатор доступа private protected

Модификатор private protected предоставляет меньше доступа, чем модификатор protected, но
больше, чем модификатор private. Элемент, определенный с модификатором private protected,
доступен только из подклассов некоего класса. Если другие модификаторы, которые мы
использовали, соответствуют концепции затенения данных, то модификатор private protected
наиболее важен при рассмотрении наследования классов.

Его убрали скорее всего потому что разработчикам захотелось, чтобы было по одному модификатору доступа. А про protected там написано:
Цитата

Модификатор protected позволяет сделать элементы класса общими только для определенного
набора классов - тех, что содержатся в том же пакете.

Кстати именно этот модификатор присваивается если ничего не указывать. А до того как я прочитал эту книжку я искренне думал, что в остальных книжках написана правда.  smile  

Автор: EvgenZ 30.6.2007, 09:10
Цитата(progdog @  30.6.2007,  08:47 Найти цитируемый пост)
Модификатор protected позволяет сделать элементы класса общими только для определенного
набора классов - тех, что содержатся в том же пакете.

Кстати именно этот модификатор присваивается если ничего не указывать. А до того как я прочитал эту книжку я искренне думал, что в остальных книжках написана правда.  smile  


Если не ошибаюсь, то, если ничего не указывать присваивается "доступ по умолчанию" или пакетный доступ. Т.е. наследник из другого пакета не будет видеть.

Автор: EvgenZ 30.6.2007, 09:31
Код

package packagepkg;

class B extends newpackage.NewClass
{
    B(){this.}  /* если "а" в NewClass с модификатором доступа паблик или протектед, то могу поставить "а", а если с доступом по умолчанию, то "а" в наследнике будет не видно, так как доступ по умолчанию действует в пределах пакета.*/
    int b;    
}
public class Main 
{
    public static void main(String[] args) 
    {
    }
    
}


Код

package newpackage;
public class NewClass 
{    
    int a = 55;     //поставить паблик, протектед или оставить по умолчанию
}

Автор: progdog 30.6.2007, 11:55
Я не знаю с чего вы взяли что при protected оно заработает, но во всяком случае в Eclipse оно выдаст ошибку. Даже если компилятор это и откомпилирует, я Eclipse выкидывать на помойку не собираюсь.  smile 

Я вот так тестил:
Код

package parent
public class Parent {
   protected void render() {}
}

Код

package child
public class Child extends Parent {
   void test() {
      render();
   }
}

Автор: LSD 30.6.2007, 14:14
Цитата(progdog @  30.6.2007,  12:55 Найти цитируемый пост)
Я вот так тестил:

Там ошибка в том, что нет импорта для Parent-а. А в остальном код полностью корректный.

Автор: progdog 30.6.2007, 19:13
Ну да, точно smile Перепечатал из исходника, про импорт забыл.

Но это все равно сути дела не меняет.

Автор: LSD 1.7.2007, 02:16
Цитата(progdog @  30.6.2007,  20:13 Найти цитируемый пост)
Но это все равно сути дела не меняет.

Какой сути? Если ты про то, что Eclipse показывает для данного кода ошибку, то выкини его. Потому как или он поддерживает язык или нафиг он вообще сдался.
Только я думаю, это ты что-то перепутал, т.к. не может Eclipse давать ошибку в таком тривиальном случае.

Автор: w1nd 1.7.2007, 04:11
progdog привёл всё же не тот пример, на котором получил ошибку. Вот если бы в классе Child метод test() был бы таким
Код
public void test() {
        Parent parent = new Parent();
        parent.render();
    }

то была бы ошибка - класс-наследник в другом пакете может вызывать protected-метод только для себя, для других объектов Child или наследников Child. 

Автор: LSD 1.7.2007, 09:23
Ну это правильное поведение, я даже видел объяснение почему так.

Автор: progdog 1.7.2007, 11:04
Извиняюсь, smile забыл сохранить parent  smile , когда проверял

Автор: niasilil 3.7.2007, 05:52
Мой преподаватель настоятельно рекомендовал не пользоваться protected в подаваляющем большинстве случаев. Либо private, либо public. 

Автор: heraclitus 3.7.2007, 06:18
"Если Вы создаете новый пакет и наследуете класс из другого пакета, то единственные члены, к которым Вы имеете доступ, это публичные члены в исходном пакете. (Конечно, если наследование происходит в том же самом пакете, Вы имеете нормальный пакетный доступ для всех “дружественных” членов.) Но иногда, создатель базового класса хочет разрешить доступ к конкретному члену только для наследуемого класса, но не всему миру в целом. Именно это делает protected".

Модификатор доступа без имени называют дружественным. "...дружественные элементы имеют доступ на уровне пакета..."
...все другие классы в том же пакете имеют доступ к дружественным членам, но для классов за пределами этого пакета, члены являются приватными (private).

Цитаты взяты из Эккель "Думаем на Java 2". 

Вывод: дружественный и защищенный модификаторы похожие, но не идентичные.

Автор: batigoal 3.7.2007, 07:43
niasilil, а почему?

Автор: niasilil 3.7.2007, 16:13
Цитата(batigoal @ 3.7.2007,  07:43)
niasilil, а почему?

Он работает на бирже, руководит QA отделом и смотрит на все со своей колокольни. То что должно быть скрыто - все private, это понятно. Никаких полумер. А то что открыто, пусть даже с дефолтным или protected модификатором, это любой другой человек из команды может использовать (и изменить) в другом месте программы. Значит отвечать кому? Правильно, тебе, потому что это твой кусок кода. Он нам говорил rule of thumb - если пишешь protected, то подумай еще раз, все шансы что ты на неправильном пути. 

Автор: batigoal 3.7.2007, 16:22
Т.е. такого случая, как необходимость доступа к полю, например, в наследнике, он даже не рассматривает?

Автор: AntonSaburov 3.7.2007, 16:27
Не говоря уже о переопределяемых методах в наследниках - вообщем-то protected достаточно удобная идея.

Автор: niasilil 3.7.2007, 16:31
Цитата(batigoal @ 3.7.2007,  16:22)
Т.е. такого случая, как необходимость доступа к полю, например, в наследнике, он даже не рассматривает?

Ну не все так плохо, рассматривал smile  Только опять же pros and cons, encapsulation, и т.д. ... Вместе с хорошим всегда идет и плохое, доступ же не только наследники получают в этом случае. В большинстве случает getters and setters лучше (уж там мы точно постараемся все проверки сделать, чтоб не дай бог какой придурок ... ну и тд)  smile
Вобщем, просто пожелаение - подумать.

Добавлено через 2 минуты и 49 секунд
Цитата(AntonSaburov @ 3.7.2007,  16:27)
Не говоря уже о переопределяемых методах в наследниках - вообщем-то protected достаточно удобная идея.

Да, конечно, никто и не спорит. 

Автор: nornad 3.7.2007, 19:14
Цитата(niasilil @  3.7.2007,  19:31 Найти цитируемый пост)
уж там мы точно постараемся все проверки сделать, чтоб не дай бог какой придурок ...

Многолетний опыт говорит о том, что как ни делай проверки, а всё равно найдётся тот самый "придурок", который сумеет-таки это дело завалить. Естественно, это не умаляет достоинств проверок как таковых. Просто, кроме проверок, надо и саму структуру объектов делать хорошей, в чём protected всё же больше помогает, чем мешает.
А вашему преподавателю я могу сказать лишь то, что у него малость не всё в порядке с мозгом. Его позиция похожа на позицию одной преподавательницы в ВУЗе, где я учился. Она считала, что GOTO - вещь опасная и ненужная, а потому его нельзя использовать. Все, кто использовали GOTO в программе, имели проблемы при сдаче задания. Я согласен, что злоупотреблять им не стоит, но бывают в жизни ситуации, когда использовать GOTO явно предпочтительнее, чем пытаться заменить его иными конструкциями. То же самое и с protected в жабе. Ваше право не использовать что-либо, но вы не сможете доказать, что это объективно обоснованно во всём спектре задач.

Автор: niasilil 3.7.2007, 21:06
Цитата(nornad @ 3.7.2007,  19:14)
...Просто, кроме проверок, надо и саму структуру объектов делать хорошей, в чём protected всё же больше помогает, чем мешает. ...

... Она считала, что GOTO - вещь опасная и ненужная, а потому его нельзя использовать. ... Я согласен, что злоупотреблять им не стоит, но ...

Мы перетираем воду в ступе, обсуждаем очевидные вещи. Причем даже не противоречим друг другу. smile 
Ваш пример про GOTO как нельзя лучше описывает ситуацию. Именно эту мысль "что злоупотреблять не стоит" я и пытался донести. Добавлю что если цена ошибки велика, то нужно рассматривать все возможные гипотетические неприятности. 

Автор: nornad 3.7.2007, 21:57
Цитата(niasilil @  4.7.2007,  00:06 Найти цитируемый пост)
Мы перетираем воду в ступе, обсуждаем очевидные вещи. Причем даже не противоречим друг другу.

Согласен, вопрос больше риторический. Я, кстати, не в плане спора с тобой (будто ты придерживаешься иного мнения), а в плане реакции на позицию твоего преподавателя. (Давай на "ты" - не такие уж мы и древние  smile ).

Цитата(niasilil @  4.7.2007,  00:06 Найти цитируемый пост)
Добавлю что если цена ошибки велика, то нужно рассматривать все возможные гипотетические неприятности.

Все в любом случае не рассмотришь, а посему лично я предпочитаю чистую и ясную структуру объектов, а не возможную защищённость кода на основе геттеров/сеттеров с не меньшей возможностью потерять читабельность из-за неочевидных действий внутри упомянутых методов.
С другой стороны, если сам объект предполагает наличие защиты при установке получении значения поля, то, естественно, эти методы просто обязательны.
Правда, такая защита для protected- и private- полей нужна, по-моему, нечасто.

Автор: LSD 4.7.2007, 11:59
Цитата(niasilil @  3.7.2007,  17:13 Найти цитируемый пост)
А то что открыто, пусть даже с дефолтным или protected модификатором, это любой другой человек из команды может использовать (и изменить) в другом месте программы. Значит отвечать кому? Правильно, тебе, потому что это твой кусок кода. Он нам говорил rule of thumb - если пишешь protected, то подумай еще раз, все шансы что ты на неправильном пути. 

А потом найдется умник которому это надо позарез, и он полезет через рефлексию smile 
Я не понимаю как можно так работать в команде, что приходится защищаться от своих-же коллег smile 
Да и при чем тут ты, это же его код привел к ошибке. Ведь если я запишу неправильные данные в файл, мне что винить разработчиков JDK, потому что они не добавили нужные проверки в FileOutputStream?

Автор: nornad 4.7.2007, 14:35
Цитата(LSD @  4.7.2007,  14:59 Найти цитируемый пост)
Я не понимаю как можно так работать в команде, что приходится защищаться от своих-же коллег

Я такое уже разок встретил. Долгой работы с этой командой у меня не вышло почему-то. smile

Автор: niasilil 5.7.2007, 04:11
Цитата(LSD @ 4.7.2007,  11:59)
Я не понимаю как можно так работать в команде, что приходится защищаться от своих-же коллег smile 

Ну так он нам и приводил примеры из жизни. Работает он на Чикагской бирже, цена ошибки - сотни тысяч, миллионы денег. Естественно, при такой потере нужен козел отпущения. Им будет тот, у кого код сработал неправильно. Если кто то изменит твой объект без всех предусмотренных проверок, то может сложится все что угодно. Виноват будет скорее всего тот кто неправильно туда записал, понятен пень. Но ведь можно и под раздачу попасть и на пару вылететь. Собственно, это не есть недоверие к работе других, это ответственность за свой участок. 
По моему так.

Автор: Maksym 5.7.2007, 12:38
Цитата(niasilil @  5.7.2007,  04:11 Найти цитируемый пост)
Ну так он нам и приводил примеры из жизни. Работает он на Чикагской бирже, цена ошибки - сотни тысяч, миллионы денег. Естественно, при такой потере нужен козел отпущения. Им будет тот, у кого код сработал неправильно. Если кто то изменит твой объект без всех предусмотренных проверок, то может сложится все что угодно. Виноват будет скорее всего тот кто неправильно туда записал, понятен пень. Но ведь можно и под раздачу попасть и на пару вылететь. Собственно, это не есть недоверие к работе других, это ответственность за свой участок. 
По моему так. 

А отдел тестирования? Если они приняли продукт и он попал в production, то все вопросы в такой ситуации только к ним.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)