Как выбрать между модификатором закрытого и защищенного доступа для инкапсуляции членов между базовыми и дочерними классами? - PullRequest
0 голосов
/ 06 октября 2019

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

Мой вопрос касается классов Parent / Child.

В моем основномВ классе я определяю все параметры следующим образом:

public class MyFatherClass
{
    private long id = -1;
    public long ID { get { return this.id; } set { this.id = value; } }    
    ...
}

Итак, во всех внутренних функциях я получаю доступ к своему личному значению, а не к общему.

Затем в моем дочернем классе я просто добавляю параметрыспецифично для дочернего класса.

public class MyChildClass : MyFatherClass
{
    private long anotherParameter = -1;
    public long AnotherParameter { get { return this.anotherParameter; } set { this.anotherParameter = value; } }    
    ...
}

Просто я вижу, что в моем родительском классе я могу без проблем получить доступ к id и ID, но из дочерних классов я могу получить доступ только к ID(поскольку id является приватным).

Если я правильно понял, мне нужно заменить все private на protected в родительской программе, так что это решит проблему? Чего я не понимаю, так это того, что код работает, даже если я оставлю это так. Почему у меня не появляется сообщение об ошибке, когда я задаю значение ID в дочернем классе, предложение this.id=value выполняется, но как я могу получить к нему доступ из моего дочернего класса, если он закрытый?

Я сейчас сомневаюсь, могу ли я просто добавить private id в каждый дочерний класс или я могу установить id для защищенного в моем родительском классе?

Спасибо за ваши объяснения.

Редактировать, просто добавив скриншот моего перевернутого кода после запутывания, чтобы вы могли понять разницу в том, как скрываются закрытые / открытые методы / поля

enter image description here

Ответы [ 3 ]

2 голосов
/ 06 октября 2019

Почему у меня нет сообщения об ошибке, когда я устанавливаю значение идентификатора в дочернем классе, выполняется предложение this.id=value, но как я могу получить к нему доступ из своего дочернего класса, если он закрытый?

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

public class Foo
{
    public void Bar()
    {
        Baz();
    }

    private void Baz()
    {
        // private method called by public method
    }
}   

var foo = new Foo();
foo.Bar();

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

Что касается защиты вашего поля (private long id = -1;): да, это будет означать, что вы можете получить к нему доступ в производномклассы. Но хотите ли вы, это другой вопрос.

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

public long ID { get; set; } = -1;

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

См. также:

1 голос
/ 06 октября 2019

Вот краткое и сокращенное описание того, что модификаторы доступа делают:

  • Public : поля (переменные) и свойства (переменные)инкапсуляция) и методы (функции и процедуры) видимы и доступны классу itslef, его дочерним элементам и любым другим внешним классам.

  • Private : members (поля, свойства и методы) видны и доступны только классу, а не его дочерним элементам и никаким внешним классам.

  • Защищено : члены видны и доступныклассом и его потомками, но не другими классами.

  • Внутренний : члены видны и доступны классу и его дочерним элементам и любому классукоторый находится в той же сборке (.exe и .dll), но не классом из другой сборки.

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

Но вот тПравило:

  • Если дочерние классы могут изменять идентификатор, вы должны установить его в качестве защищенного поля и предложить открытое свойство (get), если оно доступно для внешних элементов.

  • Если дочерним классам не разрешено изменять его, вы должны установить его как закрытое и предложить:

    • Предполагаемое свойство с только получателем, если внешние элементы не могут получить к нему доступ.

    • Открытое свойство, имеющее только геттер, если внешние элементы могут получить к нему доступ.

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

Вы можете прочитать эти руководства, чтобы лучше понять ключевые слова модификатора доступа:

Модификаторы доступа C #

Модификаторы доступа (C # Reference)

Вот некоторые показания:

Уровень обучения C # 0
Уровень обучения C # 1
Уровень обучения C # 2
C # Tutorial Level 3

C # Snippets @ Techi.io

Начало программирования на Visual C # 2008

0 голосов
/ 06 октября 2019

Класс MyChildClass, который наследуется от MyFatherClass, не может получить доступ к полю id , потому что это личное. Чтобы сделать его доступным, вам необходимо изменить модификатор доступа к полю:

protected :

////////////////////////////////////
// Dll1.dll
////////////////////////////////////

namespace Dll1
{
    public class Base
    {
        //The field we are attempting to access
        protected int a;
    }

    public sealed class Main : Base
    {
        public void DoSomething()
        {
            //Can be done sins Main inherits from Base
            base.a = 100;
        }
    }

    public class Invader
    {
        public int GetA()
        {
            var main = new Main();

            main.DoSomething();

            // can not be done sins the field is only accessible by those that inherit from Base
            return main.a;
        } 
    }
}

////////////////////////////////////
// Dll2.dll
////////////////////////////////////

namespace Dll2
{
    public class ADll2Class : Dll1.Base
    {
        public int GetA()
        {
            //Can be done because ADll2Class inherits from Dll1's Base class
            return base.a;
        }
    }

}

private protected :

То же, что и защищенный, но в вышеприведенном примере класс Dll2, ADll2Class, не сможет получить доступ к полю a, поскольку он будет защищен в частном порядке, другими словами, только классы из той же самой DLL, что иBase, которые наследуются от Base, смогут получить доступ к a.

или вы можете установить его на

внутренний :

Если поле a в приведенном выше примере было внутренним, то, так же как и private protected, класс Dll2 не сможет получить к нему доступ, но класс Invader в Dll1 сможет получить к нему доступ, поскольку он является частью того жеdll as Base.

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

...