защищенные данные в абстрактном классе - PullRequest
14 голосов
/ 20 августа 2010

Мой вопрос касается, в частности, Java, абстрактных классов и использования защищенных данных.Мне говорят, что все данные должны быть частными, и используются только защищенные методы получения / установки.

Теперь я понимаю, что мы хотим оградить данные от прямого манипулирования случайными пользователями класса и что открытые члены данныхв целом это сомнительная практика.Я посмотрел на «Защищенные поля Java против общедоступных получателей» ( Защищенные поля Java против общедоступных получателей ), но я все еще сомневаюсь, что:

protected int i;  

хуже в абстрактном классе, чем:

private int i;  
protected int geti();  
protected void seti(int j); 

Я просто не вижу обратной стороны, когда абстрактный класс существует именно для предоставления родительских / общих возможностей дочерним классам, а защищенная область предназначена для предоставления доступа детям, одновременно защищаяданные от случайных пользователей.Я отмечаю в вышеупомянутом вопросе, что большинство ответов, похоже, касаются вопроса о том, почему данные в целом должны быть частными, а не общедоступными.Я пытаюсь сосредоточить свой вопрос конкретно на данных, существующих в абстрактном родителе, предназначенном для использования детьми.Единственный разумный комментарий, который я слышал на сегодняшний день, заключается в том, что использование защищенных родителями данных (например, int i выше) оставляет вас с кодом в дочернем классе, который ссылается на переменную, не объявленную в дочернем классе.Менее убедительным является аргумент (см. Общий защищенный элемент данных в базовом классе? ), что вы можете захотеть изменить доступ однажды, и теперь вы должны соблюдать свой интерфейс.Это абстрактный класс, предназначенный для расширения в 100% случаев.

Спасибо!Определенные ссылки на книги / заголовки # страниц гораздо более полезны, чем ссылки на "... любой базовый текст программирования на Java ..." *

========================================= 10-13-2010
Это был такой же вопрос об абстрактных классах, как и об защищенных данных.Меня разочаровывает, что в ответах акцент сместился на то, является ли сокрытие данных хорошей вещью в ООП (ответ: да).Здесь много глубины, затрагивающей природу абстрактного класса, и как он отличается от обычного не финального класса, и какие возможные преимущества могут быть для исправления имен и типов элементов данных в абстрактном родительском элементе для использованиядетские классы.Я думаю, что здесь есть возможность для инноваций и большего контроля, распространяющегося от абстрактного родителя к реализующим дочерним классам.Я обеспокоен тем, что общие принципы, такие как преимущества сокрытия данных, могут стать догмой и препятствовать инновациям и разработке новых моделей и идей.

Спасибо всем, кто внес свой вклад.

Ответы [ 8 ]

11 голосов
/ 20 августа 2010

Если поле является закрытым и доступ осуществляется через методы получения и установки, вы сможете переопределить методы получения и установки (например, удаление поля и обновление / чтение значения из внешнего источника) и, таким образом, изменить способ поле "работает, не касаясь каких-либо дочерних классов.

Стоит ли это того, решать вам.

9 голосов
/ 20 августа 2010

Представьте защищенные методы как интерфейс для подклассов, точно так же, как публичные методы являются интерфейсом для всех остальных.

Предоставление средств доступа позволяет базовому классу поддерживать свое состояние:нет никакого способа, которым подкласс мог бы испортить это без преднамеренного уловки.

3 голосов
/ 20 августа 2010

Наличие меньшего доступа - это не недостаток, а выгода. Классы всегда должны ограничивать доступ к как можно большему количеству своего внутреннего состояния. Не думайте о том, почему внутренние органы должны быть скрыты, вместо этого подумайте, почему они должны быть разоблачены. В этом случае, как и в любом случае, если только нет действительно веской причины выставлять переменную, не выставляйте ее.

1 голос
/ 20 августа 2010

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

Также есть момент, который Алекс поднял ранее.

1 голос
/ 20 августа 2010

Если вам не нужно, чтобы ваш ребенок напрямую имел к нему доступ, почему вы позволили бы ему?

Это не минус для использования защищенных. Но если в этом нет необходимости, возможно, лучше избегать этого и контролировать доступ к своим полям.

0 голосов
/ 08 апреля 2012

Вы хотите использовать геттеры / сеттеры, потому что использование protected int i; позволяет переопределять поля (чего вы хотите избежать любой ценой).

Вы хотите запретить переопределение полей, поскольку оно работает иначе, чем переопределение методов.Переопределение полей не делает переопределенное поле недоступным (тип ссылки определяет, с каким экземпляром поля вы работаете).

Доступные поля должны быть окончательными или в классе, который является окончательным.

public class OverridingFun {
    public static class Base {
        public int i = 1;
        public int getI(){ return i; }
    }
    public static class A extends Base {
        public int i = 2;
        public int getI(){ return i; }
    }
    public static class B extends A {
        public int i = 3;
        public int getI(){ return i; }
    }
    public static void main(String [] args){
        B b = new B();
        A bAsA = b;
        Base bAsBase = b;

        System.out.println(b.getI());//3
        System.out.println(bAsA.getI());//3
        System.out.println(bAsBase.getI());//3

        System.out.println(b.i);//3
        System.out.println(bAsA.i);//2
        System.out.println(bAsBase.i);//1

        b.i = 4;
        bAsA.i = 5;
        bAsBase.i = 6;

        System.out.println(b.i);//4
        System.out.println(bAsA.i);//5
        System.out.println(bAsBase.i);//6
    }
}

На первый взгляд это выглядит как нечто, что делает код трудным для чтения, но это влияет на функциональность.Скажем, поле переопределяется производным классом, так как сеттеры не используются, нет способа автоматически обновить базовое поле и нет способа обнаружить, изменил ли кто-либо базовое поле (поскольку базовое значение все еще доступно), иобновить производное поле.Легко представить, что базовое и производное состояния могут быть не синхронизированы, и что ошибки будет трудно отследить.Проще говоря, это очень хрупкий API.

К сожалению, от этого не существует способа защиты, поскольку ключевое слово final, которое защищает от переопределения, также делает поля однократными при записи.Поэтому нет перезаписываемых не перегружаемых полей.

Лично я довольно удивлен, что разработчики языка вообще допускают переопределение полей.Преимущество использования сеттеров состоит в том, что каждый уровень может гарантировать целостность своего собственного состояния и полагать, что производные классы не испортили его.Переопределение поля просто напрашивается на неприятности.

0 голосов
/ 20 августа 2010

Сокрытие информации ценно даже среди классов, связанных с наследованием.

В дополнение к разрешению повторной реализации, как отметил Алекс выше:

  • Вы можете установить точки останова в методах.
  • Вы можете добавить ограничения в одном месте.
0 голосов
/ 20 августа 2010

Если кто-то создает подклассы вашего класса и помещает подкласс в тот же пакет, что и ваш текущий класс, он может переопределить ваши методы получения и установки. Например, они хотят убедиться, что i может быть установлено только на значение больше 1.

Кроме этого, это действительно ваше дело. Соглашение состоит в том, что есть геттеры и сеттеры для всего, хотя.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...