Общественный против Защищенного - PullRequest
3 голосов
/ 18 января 2012

Я не совсем понимаю, почему классы составляют public и protected методы / переменные.Почему только расширенные классы могут получить доступ к protected методам / переменным?Может кто-нибудь еще может помочь мне осветить разницу между public и protected и его функциональностью.

Ответы [ 4 ]

9 голосов
/ 18 января 2012

Почему только производные классы могут иметь доступ к защищенным членам?

Потому что это определение"защищено". Доменом доступности защищенного члена является класс и его производные классы.

Возможно, вы намеревались спросить:

Почему я не могу всегда обращаться к защищенному члену, даже когда я нахожусь в производном классе?

Это сложно. Подробное объяснение см. В моей серии из шести статей «Почему я не могу получить доступ к защищенному члену из производного класса?»

http://blogs.msdn.com/b/ericlippert/archive/tags/protected/

4 голосов
/ 18 января 2012

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

Модификаторы доступа (а также public и protected, существует private, internal и protected internal) - это средства, позволяющие сделать код максимально понятным и уменьшить количество ошибок.

Существуют языки без какой-либо формы инкапсуляции. В крайнем случае, любой код может изменить любую часть любых данных. Дисциплинированный кодер уменьшит количество мест, которыми манипулирует данный тип данных, но все еще может быть неочевидным все комбинации операций, которые могут оставлять объекты * в разных состояниях. Ситуация ухудшается, когда их код используется как часть чужого кода.

Модификаторы доступа помогают нам справиться с этим. По умолчанию у нас есть личные участники. Тогда единственные места, к которым член может получить доступ, находятся внутри самого класса. Это значит:

  1. Единственная ошибка в том, как ими можно манипулировать, находится внутри класса.
  2. Единственный код, который должен заботиться о поддержании этих членов в согласованном состоянии, находится внутри класса, и этот код не должен беспокоиться о возможности другого кода, нарушающего это.
  3. Вы можете получить полное представление обо всех способах манипулирования этими полями, взглянув на определение одного класса, которое обычно содержится в одном файле и редко более чем в двух.

Это значительно облегчает нам кодирование.

Конечно, класс, где все приватно, не очень полезен. Мы обычно должны позволить некоторым членам быть публичными. Обычно у нас есть поля приватные, некоторые полезные методы приватные, а затем некоторые открытые методы и свойства используют их. Мы все еще можем исследовать все возможные манипуляции с закрытыми членами, изучая только этот один класс, хотя мы открыли вызов членов, которые делают это с другими классами. Таким образом, эти члены предоставляют нам интерфейс между кодом внутри и снаружи класса, границу, через которую мы защищаем состояние класса от ошибок, обеспечивая при этом полезную функциональность для другого кода.

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

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

Меньше случаев, когда он используется, потому что обычно мы либо можем держать вещи в секрете - что безопаснее - либо должны быть публичными, чтобы быть полезными. Одним из наиболее распространенных случаев является то, что открытые члены предоставляют функциональность и защищенные средства определения для ее реализации. Например, HttpEncoder предоставляет несколько методов для решения проблемы кодирования строк для HTML, но есть два защищенных абстрактных метода, которые переопределяют производные классы, чтобы обеспечить функциональность, общую для нескольких различных методов. Внешние классы не нуждаются в доступе к ним, но производные классы делают это.

Практический пример. Скажем, у нас есть базовый класс, который реализует INotifyPropertyChanging. Этот интерфейс означает, что он должен отслеживать обработчики PropertyChangingEventHandler и вызывать события, когда свойство собирается измениться.

Мы не хотим, чтобы внешние классы вызывали это событие, потому что это не их дело, и их получение просто приведет к ошибкам.

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

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

* Люди из объектно-ориентированного фона могут даже не считать такие фрагменты данных «объектами».

2 голосов
/ 07 февраля 2017

Меня также смутили public и protected.

Переменная (или метод) protected НЕ может быть доступна из экземпляра (созданного с помощью new);к нему можно получить доступ только из подкласса, который расширяет суперкласс (расширенный с extends).

Этот Java-подобный пример должен помочь прояснить разницу.

// Super-Class: Vehicle
public class Vehicle {

  // (1) I'm a protected variable
  protected String engine = "engine";

}

// Sub-Class: Car
public class Car extends Vehicle {

  public String printEngineSuccess() {
    // (2) We can print a protected variable,
    // from within this class because it extends
    // the super-class `Vehicle`.
    System.out.println(super.engine); // --> SUCCESS
  }

  public String printEngineError() {
    // (3) We can NOT print a protected variable,
    // from a `new` instance of the super-class `Vehicle`.
    Vehicle vehicle = new Vehicle();
    System.out.println(vehicle.engine); // --> ERROR
  }

  public static void main (Strings[] args) {
    printEngineSuccess();
    printEngineError();
  }
}
1 голос
/ 18 января 2012

Предполагается, что это в контексте языка, подобного Java.

  • public - можно получить доступ из любого класса
  • protected - можно получить из подпрограммы /только производный класс
...