Подтвердить что ты не робот

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

У меня есть абстрактный класс AbsClass, который реализует интерфейс, IClass. Класс IClass имеет пару свойств только с Access accessors. AbsClass реализует свойства IClass как абстрактные свойства, которые должны быть определены в классах, полученных из AbsClass.

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

ConcClassA.Bottom.Set не может переопределить, поскольку AbsClass.Bottom не имеет переопределяемого набора

См. ConcClassA ниже.

Если у меня есть класс, который реализует интерфейс IClass, но не наследует от AbsClass, тогда я могу добавить набор аксессуаров без проблем. Подробнее см. ConcClassB.

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

public interface IClass
{
    double Top
    {
        get;
    }
    double Bottom
    {
        get;
    }
}

abstract class AbsClass:IClass
{
    public abstract double Top
    {
        get;
    }

    public abstract double Bottom
    {
        get;
    }
}



class ConcClassA : AbsClass
{
    public override double Top
    {
        get { return 1; }
    }

    public override double Bottom
    {
        get { return 1; }

        //adding a Set accessor causes error:
        //ConcClassA.Bottom.Set cannot override because AbsClass.Bottom does not have an overridable set accessor

        //set { }
    }

}

class ConcClassB : IClass
{
    public double Top
    {
        get { return 1; }
        //added a set accessor to an interface does not cause problem
        set { }
    }
    public double Bottom
    {
        get { return 1; }
    }
}

Обновление

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

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

RhNodeBuilding реализует интерфейс IBuilding, который определяет количество свойств только для чтения, которые должны иметь все здания, такие как TopElevation BottomElevation, Высота, NumberOfFloors и т.д. и т.д. Имейте в виду, что существуют другие типы зданий, которые не происходят из RhNodeBuilding, но все же необходимо реализовать IBuilding.

Сейчас у меня есть два типа, которые происходят из RhNodeBuilding: MassBuilding и FootPrintBuilding. MassBuilding определяется трехмерной формой, созданной пользователем. Эта форма имеет TopElevation и BottomElevation, которые должны быть доступны через соответствующие свойства, но вы не сможете редактировать 3D-объем, изменяя свойства.

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

Итак, в резюме. Все здания (IBuildings) должны иметь возможность возвращать TopElevation и BottomElevation, но не все здания должны разрешать TopElevation > или BottomElevation. Все RhNodeBuildings IBuildings, а классы, которые производятся от RhNodeBuilding, могут или не должны иметь возможность напрямую устанавливать TopElevation. > и BottomElevation.

public interface IBuilding
{
    double Top
    {
        get;
    }
    double Bottom
    {
        get;
    }
}

abstract class RhNodeBuilding:IBuilding
{
    public abstract double Top
    {
        get;
    }

    public abstract double Bottom
    {
        get;
    }
}



class MassBuilding: AbsClass
{

   //mass building only returns Top and Bottom properties so it works fine
    public override double Bottom
    {
        get { return 1; }
    }

    public override double Top
    {
        get { return 1; }
    }

}


class FootPrintBuilding: AbsClass
{
    //Top and Bottom of FootPrintBuilding can both be retrieved and set
    public override double Top
    {
        get { return 1; }
        //adding a Set accessor causes error:
        //cannot override because RhNodeBuilding.Top does not have an overridable set accessor

        //set { }
    }

    public override double Bottom
    {
        get { return 1; }

        //adding a Set accessor causes error:
        //cannot override because RhNodeBuilding.Bottom does not have an overridable set accessor

        //set { }
    }

}

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

abstract class AltRhNodeBuilding
{
    public abstract double Top
    {
        get;
    }
}


class AltFootPrintBuilding: IClass
{
    public override double Top
    {
        get { return 1; }

       //Can't add set access to overridden abstract property
        set { }
    }

    //No problem adding set accessor to interface property
    public double Bottom
    {
        get { return 1; }
        set {  }
    }
}
4b9b3361

Ответ 1

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

Что вы можете сделать, это переопределить и затенять реализацию базового класса и предоставить свои собственные свойства чтения/записи. Я не знаю, как это сделать, не вводя дополнительный класс в иерархию:

class AbsClassB : AbsClass
{
    public override double Top { get { return ((ConcClassB)this).Top } }
    public override double Bottom { get { return ((ConcClassB)this).Bottom } }
}


class ConcClassB :  AbsClassB
{
    new public double Top
    {
        get { ... }
        set { ... }
    }

    new public double Bottom
    {
        get { ... }
        set { ... }
    }
}

Лучшей идеей было бы определить защищенный виртуальный метод прямо в AbsClass и реализовать Top.get и Bottom.get в терминах этого метода. Затем вы можете переопределить этот метод непосредственно в ConcClassB и затенять свойства без необходимости в дополнительном классе:

abstract class AbsClass : IClass
{
    public double Top
    {
        get { return GetTop(); }
    }

    public double Bottom
    {
        get { return GetBottom(); }
    }

    protected abstract double GetTop();

    protected abstract double GetBottom();
}

class ConcClassB :  AbsClass
{
    new public double Top
    {
        get { ... }
        set { ... }
    }

    new public double Bottom
    {
        get { ... }
        set { ... }
    }

    protected override double GetTop()
    {
        return Top;
    }

    protected override double GetBottom()
    {
        return Bottom;
    }
}

Ответ 2

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

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

Ответ 3

Используйте глобальную переменную.