@splunk

C#. Операторы доступа для сокрытия, но не для защиты?

Как я понял, модификаторы доступа нужны только для сокрытия членов класса, но не для защиты (рефлексия). Они лишь помогают понять разработчику, к каким членам класса у него есть доступ.
Грубо говоря, это всё нужно только для того, чтобы поставив оператор доступа точку " . ", разработчик не видел лишнего "мусора", который ему не следует трогать.

Если это единственная функция, то почему в учебных пособиях эта тема так раздута? Каждый автор сует эти модификаторы доступа в самый убогий код. Это пригодится только в совместных проектах. Стоит с этим заморачиваться, когда пишешь один и для себя?
  • Вопрос задан
  • 528 просмотров
Решения вопроса 1
lexxpavlov
@lexxpavlov
Программист, преподаватель
Инкапсуляция нужна не для защиты самого кода (вы правильно сказали - всё всегда можно увидеть), а для того, чтобы защитить код, использующий класс, от изменений этого класса. Есть такие два понятия - интерфейс и реализация. У любого класса должно быть назначение (и желательно - только одно назначение), и те элементы, относящиеся к назначению, делают публичным. А те элементы, которые не связаны с самой задачей и предназначены для вспомогательных функций, то это закрытые элементы, пользователю этого класса они не нужны.

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

Как пример, пусть будет такой класс для решения квадратного уравнения:
class KvadrUr
{
    public double A { get; set; }
    public double B { get; set; }
    public double C { get; set; }

    public bool HasRoots { get { return GetDiscr() >= 0; } }

    public KvadrUr()
    {
    }

    public KvadrUr(double a, double b, double c)
    {
        A = a;
        B = b;
        C = c;
    }

    public double[] GetRoots()
    {
        var discr = GetDiscr();
        if (discr < 0) return new[] {double.NaN, double.NaN};
        var sqrt = Math.Sqrt(discr);
        return new[]
        {
            (-B + sqrt) / (2 * A), 
            (-B - sqrt) / (2 * A)
        };
    }

    private double GetDiscr()
    {
        return B*B - 4*A*C;
    }
}

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

А теперь представьте, что получение дискриминанта будет публичным методом. Тогда кто-нибудь возьмёт и начнёт использовать этот метод в своём коде. И если автор класса захочет и изменит реализацию на другой способ (по формуле Виета, например), то дискриминант уже будет не нужен, и метод GetDiscr() нужно будет удалить. Но в том месте, где его использовали, будет ошибка - метод GetDiscr() не существует.

Таким образом, если в классе есть точное указание, что является интерфейсом, а что реализацией, даёт коду больше возможности на изменение этого кода.

Во многих языках программирования имеется особенная возможность, связанная с интерфейсами. В C# это одноимённое понятие - interface. В данном примере хорошо бы создать такой интерфейс:
interface IRoots
{
    bool HasRoots { get; }
    double[] GetRoots();
}
class KvadrUr : IRoots
{
    // ...
}

Можно создать несколько разных классов - один считает через дискриминант, другой - через формулу Виета, третий - через выделение полного квадрата, четвёртый - кубическое уравнение, пятый - биквадратное уравнение. Но каждый из классов реализуют один и тот же интерфейс, и каждый из них может быть взаимозаменяем.
Ответ написан
Пригласить эксперта
Ответы на вопрос 6
Casper-SC
@Casper-SC
Программист (.NET)
В каком энтерпрайзе? Это как рассуждение, что одежда нужна лишь для показухи и чтобы прилично выглядеть среди людей, детей и т.д., а дома можно ходить и голым. Так же можно придраться к любому принципу программирования. Вот забьёшь ты на всё это, тебя самого не будет парить, что у тебя в привычку входит быдлокодить? Следовательно у тебя не развивается определённый навык, ведь ты не паришься о сокрытии. Да и сам ты через месяца разберёшься в своём большом проекте, что можно вызывать из вне, что нет.

А зачем вообще классы? Давай всё в один класс, но у каждого метода будет префикс, чтобы понятно было, а то ещё точку ставить надо. Вот ещё!
Ответ написан
Предствим следующу ситуацию:

Человек N узнал про модификаторы доступа и решил, что они не нужны. Т.е. следуя этой логики необходимо выбросить огромный пласт приемов и условностей, которые создавались на протяжении десятков лет по одной простой причине - упростить разработку ПО...

Эм.. как вы считаете, захочется ли комуто отвечать этому человеку всерёз?

Если вы не поняли сути вопроса не нужно бежать на форум и строчить вопрос, который уже мог быть задан 100500+ раз такими же как вы.

По сути вопроса:
Заморачиватся над этим необходимо, поскольку это существенно упрощает жизнь вам и остальным. При помощи модификаторов вы должны описать, то как необходимо пользоватся вашим классом, защитить его от не желательного вмешательства и кривых рук. То что все это можно поламать при помощи рефлексии не значит, что на это стоит просто забить... Рефлексия это тоже инструмент призваный помочь в решении определеного круга задач и то как его использовать напрямую зависит от разработчика...
Ответ написан
yarosroman
@yarosroman Куратор тега C#
C# the best
Это в С# есть рефлексия и метаданные у классов, в том же С++ все это отсутствует. Плюс не во всех случаях рефлексия работает. Плюс в будущем, придется использовать библиотеку, и вы просто забудете, что можно трогать (если все публичным сделать), а что нельзя.
Ответ написан
Комментировать
@Sing303
Инкапсуляция позволяет повысить надёжность программы и делает код более самодокументированным.

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

Не понятно, почему вы не хотите следовать инкапсуляции в своих проектах, разве это добавляет сложности?
Ответ написан
@VZVZ
Reverse-Engineer, Software Developer, Architect
А если пишешь один для себя, то обязательно пишешь такой говнокод, где нет архитектуры, все навалено прям в button_click, и поэтому и точку ставить негде в принципе, и у классов нету членов нуждающихся в сокрытии, ибо в общем-то и нет ни членов, ни классов? Серьезно?

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

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

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы