Название этого типа наследования семантического - PullRequest
4 голосов
/ 19 января 2011
public class _base 
{ 
    protected int x = 5;
    protected int GetX(_base b) { return b.x; }
}


public class _derived : _base 
{ 
    public int Foo()
    {
        var b = new _base();
        //return b.x;  // <-- this would be illegal
        return GetX(b); // <-- This works and does exactly the same as the line above
    }
}

(Пожалуйста, не меняйте код. Он работает и показывает проблему.)

Ошибка:

Cannot access protected member '_base.x' via a qualifier of type '_base'; the qualifier must be of type '_derived' (or derived from it)

Обратите внимание, потому что b имеет тип _base имы не в базе, мы не можем получить доступ к защищенным членам.Я предполагаю, что причина в том, что _base может иметь некоторый другой производный тип и, следовательно, он не защищает код, но это не главное.То, что я делаю, - это создаю обходной путь для вышеуказанной проблемы, используя дополнительные защищенные методы.Это дает мне поведение, которое я хочу, и защиту, которую я хочу.Хотелось бы, чтобы было ключевое слово, которое разрешает такой доступ, но его нет.Меня интересует, есть ли у этого «шаблона» имя.

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

Ответы [ 4 ]

3 голосов
/ 19 января 2011

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

Очевидно, что это недостаток языка, но, поскольку он не используется в 99,9% случаев, он не нужен. В любом случае в C # нет ключевого слова, которое предложит то, что вы хотите.

2 голосов
/ 19 января 2011

ОБНОВЛЕНИЕ: переписать этот ответ, так как вопрос был переписан.

Мне неизвестно какое-либо название для рисунка, который вы проиллюстрировали.

Как вы думаете, причина этогоНедопустим доступ к полю, потому что мы не знаем, что экземпляр b является экземпляром _derived.«защищенный» доступ означает, что _derived разрешен доступ только к защищенным членам экземпляров _derived ;ему не разрешен доступ к защищенным членам экземпляров SomeOtherType, который также является производным от _base.

Теперь, если вопрос действительно таков: есть ли способ получить прямой доступ кчлен x от каждого производного класса до любого экземпляра? "тогда да.Вы отвергаете очевидное решение сделать его внутренним.(*) Есть другой способ.Сделайте это:

abstract class B
{
    private B() {}
    private int x;
    private class D1 : B { }
    private class D2 : B { }
    public static B MakeD1() { return new D1(); } 
    public static B MakeD2() { return new D2(); }
}

Теперь методы B и методы производных классов D1 и D2 способны напрямую обращаться к this.x, но методы других типов не способны это сделать.Нет других производных типов, кроме D1 и D2;не может быть, потому что единственный конструктор B является закрытым.И не может быть никаких экземпляров B, которые не являются D1 или D2, потому что они абстрактны.


(*) Помните, что если вы делаете это внутренне, то единственные люди, которым вы должны беспокоиться о доступе к вашему члену, это ваши сотрудники .Снизить их в обзоре кода, если они делают что-то оскорбительное для участника, - вполне приемлемое решение.

0 голосов
/ 19 января 2011

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

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

class A : _base { 
     void Foo() {
         x = 10; //or base.x = 10;
         SetX(10); //or base.SetX(10);
         Console.WriteLine(GetX()); //or base.GetX()
     }
}

Кроме того, вас может заинтересовать конструкция Properties , которая является хорошим синтаксическим сахаром для уродливых шаблонов Java getX и setX.

0 голосов
/ 19 января 2011

Инкапсуляция.

http://en.wikipedia.org/wiki/Encapsulation_(object-oriented_programming)

В основном вы контролируете, кто имеет доступ к членам через средства доступа («сеттеры» и «геттеры»).Как лежат в основе данные остаются скрытыми для пользователя.

Подумайте об этом:

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

Вы нарушите этот код.

class derived
{
  void DoSomething() { x += 1; } // x renamed, doesn't compile anymore
}

Теперь, с инкапсуляцией, поскольку x не может получить прямой доступ, мы получили методы доступа:

class derived
{
  void DoSomething() { SetX(GetX() + 1); } // No prob!
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...