Какова польза частных переменных? [Дубликат]

    

У этого вопроса уже есть ответ:

    

В то время как я никогда не использовал язык, на котором была встроенная конфиденциальность переменных, книга, которую я читаю Дугласом Крокфордом, объясняет способ создания конфиденциальности в JavaScript, но для меня это не имеет смысла. Термин «частный» не является чем-то, что я считаю возможным даже в среде программирования, так как все, работающие над кодом, могут потенциально изменить любой изменяемый объект или метод?

Итак, две вещи, которые не имеют для меня смысла, - это

  • как конфиденциальность будет полезной
  • Как определяется конфиденциальность - принципиально один разработчик не может держать что-то в исходном коде абсолютно приватным («неприкасаемым», как я понимаю) от другого разработчика, так где же рассматривать переменную «private»? Когда его трудно достичь?

Может кто-нибудь объяснить это, возможно, с примером «реального мира»?

6 голосов | спросил Viziionary 22 ndEurope/Moscowp30Europe/Moscow09bEurope/MoscowTue, 22 Sep 2015 18:28:27 +0300 2015, 18:28:27

5 ответов


15

Конечно, разработчик с доступом к исходному коду может начать манипулировать тем, что они хотят. И в процессе сделать что-то очень хрупкое и неподвластное.

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

Я точно не знаю, как Javascript обрабатывает конфиденциальность, но на таких языках, как Java и C ++, существует некоторая поддержка компилятора для обеспечения конфиденциальности.

Рассмотрим класс, представляющий IP-адрес:

public class IpAddress {

  public string ipAddress;

}

В настоящее время любой может поместить все, что захочет, в ipAddress (это общедоступное поле).

IpAddress ia = new IpAddress();
ia.ipAddress = "weeeee!";

Последнее, что я проверил, weeeee! не был действительным IP-адресом. Но, делая это частным, мы можем убедиться, что неверные адреса выбрасываются. Конечно, нам все равно понадобится доступ к нему и его обновление. Поэтому мы делаем общедоступные методы:

public class IpAddress {

  private string ipAddress;

  public string toString() {
    return ipAddress;
  }

  public boolean setipAddress(string newIp) {

    if (isValid(newIp)) {
      ipAddress = newIp;

      return true;

    } else {
      return false;
    }
  }

}

Обратите внимание, что теперь у нас есть доступ к значению IP-адреса, и мы можем его обновить, но теперь мы можем быть уверены, что когда он будет обновлен, новое значение будет действительным значением, а не чем-то вроде weeeee!

ia.ipAddress = "this won't compile";
ia.setipAddress("This won't update the address");
ia.setipAddress("192.168.0.1"); // works

Точно так же, если мы решим, что string - плохой способ хранения IP-адреса? Может быть, квартет int s будет лучше. Раньше, когда поле ipAddress было общедоступным, любой код, который использовал его, просто для его просмотра или для его изменения, мы попытались изменить нашу схему хранения. Но поскольку мы используем общедоступные методы доступа вместо прямого доступа к полю, мы можем сделать это, не нарушая ничего:

public class IpAddress {

  private int part1;
  private int part2;
  private int part3;
  private int part4;

  public string toString() {
    return "" + part1 "." + part2 + "." + part3 + "." + part4;
  }

  public boolean setipAddress(string newIp) {

    if (isValid(newIp)) {
      part1 = extractOct(newIp,1);
      part2 = extractOct(newIp,2);
      part3 = extractOct(newIp,3);
      part4 = extractOct(newIp,4);

      return true;

    } else {
      return false;
    }
  }

}

С точки зрения любого, кто использует этот класс, он выглядит так: сохраняя IP-адрес как string или четыре ---- +: = 11 = + ---- s:

int

, и им не нужно знать, или заботиться о том, чтобы вещи менялись за кулисами. *

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

ответил 8bittree 22 ndEurope/Moscowp30Europe/Moscow09bEurope/MoscowTue, 22 Sep 2015 18:35:14 +0300 2015, 18:35:14
9

Представьте, что вы пишете библиотеку javascript, и вы определили переменную size, в которой вы храните некоторый размер. Поскольку вы не инкапсулируйте его, он попадает в глобальное пространство имен.

Теперь кто-то приходит и присваивает значение size, не зная, что вы уже определили его. О, Боже. Он просто сломал вашу библиотеку. И когда вы снова назначаете size, вы нарушаете его код.

Теперь выпейте тост за инкапсуляцию.

ответил Robert Harvey 22 ndEurope/Moscowp30Europe/Moscow09bEurope/MoscowTue, 22 Sep 2015 18:50:43 +0300 2015, 18:50:43
2

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

Например, предположим, что вы хотите создать Fraction. Это требует некоторой функциональности. Предположим, он должен иметь возможность проверить равенство с другой долей. (Реально это, вероятно, должно быть намного больше, но давайте просто просим). Нам также нужно правило: фракция всегда может быть уменьшена (2/4 = 1/2).

Давайте попробуем (я буду использовать синтаксис C # -ish, а не javascript, но он должен быть достаточно читаемым):

public class Fraction
{
    public int Numerator;
    public int Denominator;

    public Fraction(int numerator, int denominator)
    {
        Numerator = numerator;
        Denominator = denominator;
        Reduce();
    }

    public void Reduce()
    {
        //Some implementation here to reduce this fraction
    }

    public bool Equals(Fraction other)
    {
        return Numerator == other.Numerator && Denominator == other.Denominator;
    }
}

Это работает? Ну нет. Что делать, если кто-то это делает:

var aHalf = new Fraction(1,2);
var anotherHalf = new Fraction(2,4);
var same = aHalf.Equals(anotherHalf);  // This is true

anotherHalf.Numerator = 2;
anotherHalf.Denominator = 4;
same = aHalf.Equals(anotherHalf);  // This is false!

Возможно, вы попытаетесь поместить вызов Reduce() внутри Equals. Но тогда, если вы это сделаете:

var aHalf = new Fraction(1,2);
var anotherHalf = new Fraction(2,4);
anotherHalf.Denominator = 2;
anotherHalf.Equals(aHalf);

anotherHalf.Numerator = 1;
var same = anotherHalf.Equals(aHalf); // This is false!

Из-за неожиданной модификации внутри Equals, этот код, который выглядит так, должен привести к anotherHalf составляет 1/2, это фактически 1/1. Еще более ожидаемый, если бы вы сделали aHalf.Equals(anotherHalf), вы имели бы противоположный результат.

Какая запутанная и сложная ситуация мы создали для себя! И почему? Если вы оглядываетесь назад, единственной функциональностью, которую мы решили использовать Fraction, является выдержка Equals. Итак, почему мы также выставляем Numerator и Denominator и сделать так сложно правильно реализовать поведение, которое нам действительно нужно? Все, что вам нужно сделать, это сделать эти private, и наша начальная реализация работает без дальнейших проблем.

ответил Ben Aaronson 22 ndEurope/Moscowp30Europe/Moscow09bEurope/MoscowTue, 22 Sep 2015 19:15:04 +0300 2015, 19:15:04
1

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

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

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

ответил Andy Dalton 22 ndEurope/Moscowp30Europe/Moscow09bEurope/MoscowTue, 22 Sep 2015 18:48:35 +0300 2015, 18:48:35
1

Насколько я понимаю, «инкапсуляция» в первую очередь касается защиты внутреннего состояния системы, которую вы разрабатываете.

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

class Arithmetic
{
    private int j;
    private int k;

    public Arithmetic(int j, int k)
    {
        this.j = j;
        this.k = k;
    }

    public int returnProduct()
    {
        return this.j * this.k;
    }

    public int returnSum()
    {
        return this.j + this.k
    }
}

В этом примере единственная точка входа для изменения состояния внутри класса - через конструктор. Поэтому, когда вы создаете объект типа Arithmetic, вы знаете вне тени сомнения, что j и k, когда вы идете на вызов returnProduct и returnSum.

Теперь давайте посмотрим на него снова, но с установщиком на одной из переменных:

class Arithmetic
{
    private int j;
    private int k;

    public Arithmetic(int j, int k)
    {
        this.j = j;
        this.k = k;
    }

    public setj(int j)
    {
        this.j = j;
    }

    public int returnProduct()
    {
        return this.j * this.k;
    }

    public int returnSum()
    {
        return this.j + this.k
    }
}

Теперь, если кто-то создает экземпляр объекта типа Arithmetic, а затем кто-то позже принимает тот же объект и обновляет одно из его полей с помощью setter, объект может возвращать неожиданное поведение.

Итак, чтобы обобщить цель приватизации или «инкапсуляции» (один из трех столпов программирования OO), в первом примере то, что мы делаем, сводится к минимуму способности программиста изменять состояние объекта.

Чем больше мы кодируем в этом стиле, тем более уверены, что мы состоим в состоянии нашей системы в любой момент времени, и тем меньше ошибок, чем у нашего кода.

Итак, общее эмпирическое правило:

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

ответил mcraen 22 ndEurope/Moscowp30Europe/Moscow09bEurope/MoscowTue, 22 Sep 2015 22:54:40 +0300 2015, 22:54:40

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132