添加一组访问到一个属性,从一个抽象类派生,只有get访问类 [英] Adding a set accessor to a property in a class that derives from an abstract class with only a get accessor

查看:87
本文介绍了添加一组访问到一个属性,从一个抽象类派生,只有get访问类的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个抽象类, AbsClass 实现接口,的iCLASS 的iCLASS 有只获得访问几个属性。 AbsClass 实现的属性的iCLASS 为抽象属性中,从 AbsClass 派生类中定义。



因此​​,所有从派生的类的 AbsClass 将还需要通过具有相同的属性,以满足的iCLASS 获取访问。然而,在某些情况下,我希望能够设置访问从的iCLASS 添加到该属性。然而,如果我试图覆盖在抽象属性的 AbsClass 有一组访问我得到这个错误



ConcClassA.Bottom.Set不能由于覆盖AbsClass.Bottom没有一个重写的set访问



请参阅 ConcClassA 之下。



如果我有一个类,只是实施的iCLASS 接口,而不是从AbsClass继承然后我可以添加一组访问与出的问题。请参阅 ConcClassB 之下。



我可能只是在AbsClass的每个推导实施的iCLASS而不是直接AbsClass。然而,我从我的设计,每一个AbsClass需要也是一本的iCLASS知道,所以我宁愿指定层次结构中的上涨。

 公共接口的iCLASS 
{
双顶
{
获得;
}
双底
{
搞定;
}
}

抽象类AbsClass:iCLASS非
{
公共抽象的双顶
{
搞定;
}

公共抽象双底
{
搞定;
}
}



类ConcClassA:AbsClass
{
公众覆盖双顶
{
{返回1; }
}

公众覆盖双底
{
{返回1; }

//添加set访问会导致错误:
//ConcClassA.Bottom.Set无法重写,因为AbsClass.Bottom没有一个重写的set访问

//集合{}
}

}

类ConcClassB:iCLASS非
{
公共双顶
{
{返回1; }
//添加一组访问到一个界面不会引起问题
组{}
}
公共双底
{
{返回1 ; }
}
}






更新



所以我觉得这会更有意义,如果我解释什么,我试图做而不是使用抽象的例子。我一个建筑公司工作,这些都涉及到一个建筑设计项目的业务对象。



我有一个抽象类的 RhNodeBuilding 表示一种建立在一个项目。有一些常规功能,比如有地板的能力,在 RhNodeBuilding定义 RhNodeBuilding 也继承了另一个抽象类,允许它是一个更大的项目树结构的一部分。



RhNodeBuilding 工具从接口的 IBuilding 定义只读属性,所有的建筑物应能提供如许多的 TopElevation BottomElevation 身高 NumberOfFloors ,etc..etc ..请注意,你是不派生自其他建筑类型的 RhNodeBuilding ,但仍需要实施<强> IBuilding



现在我有两种类型,从 RhNodeBuilding 导出为 MassBuilding 和< STRONG> FootPrintBuilding 。 MassBuilding 是由用户创建的3D形状定义。塑造有一个 TopElevation BottomElevation 将可通过相应的属性访问,但你不应该能够编辑通过改变其属性的三维体积。



<强> FootPrintBuilding 另一方面是由封闭曲线和高度范围通过挤出该曲线限定。所以不仅应该类能够返回什么当前海拔是但这些升高也应该能够被改变,重新定义的高度范围内。



因此​​,在总结。所有建筑( IBuildings )需要能够返回 TopElevation BottomElevation ,但不是所有的建筑应该允许 TopElevation BottomElevation 可直接设置。所有的 RhNodeBuildings IBuildings ,然后从派生的类的 RhNodeBuilding 可能会或可能不会需要能够直接将 TopElevation BottomElevation

 公共接口IBuilding 
{
双顶
{
获得;
}
双底
{
搞定;
}
}

抽象类RhNodeBuilding:IBuilding
{
公共抽象的双顶
{
搞定;
}

公共抽象双底
{
搞定;
}
}



类MassBuilding:AbsClass
{

//大规模建设只返回首页和Bottom属性,以便它工作正常
公众覆盖双底
{
{返回1; }
}

公众覆盖双顶
{
{返回1; }
}

}


类FootPrintBuilding:AbsClass
{
//顶部和底部FootPrintBuilding的既可以是检索和设置
公众覆盖双顶
{
{返回1; }
//添加set访问会导致错误:
//不能覆盖,因为RhNodeBuilding.Top没有一个重写的set访问

//设置{}
}

公众覆盖双底
{
{返回1; }

//添加set访问会导致错误:
//不能覆盖,因为RhNodeBuilding.Bottom没有一个重写的set访问

//设置{}
}

}

现在,它似乎是最好的选择是没有的 RhNodeBuilding 实施 IBuilding ,而是有充分的,从派生类的 RhNodeBuilding 实施IBuilding。这样我可以定义从 IBuilding 直接而不是作为替代。

 抽象类AltRhNodeBuilding $属性b $ b {
公共抽象的双顶
{
搞定;
}
}


类AltFootPrintBuilding:iCLASS非
{
公众覆盖双顶
{
获得{返回1; }

//不能添加到重写抽象属性
组组访问{}
}

//没问题,增加set访问接口物业
公共双底
{
{返回1; }
集合{}
}
}


解决方案

这工作确实因为属性是不是真正虚拟的方式 - 他们的存取方法。因此,你不能覆盖设置,如果没有一个在基类。



你可以做的是覆盖和阴影的基类的实现,并提供自己的新的读/写性能。我不知道有什么办法做到这一点没有层次结构中引入额外的类:

 类AbsClassB:AbsClass 
{
公众覆盖双顶{{返回((ConcClassB)本).TOP}}
公众覆盖双底{{返回((ConcClassB)本).Bottom}}
}


类ConcClassB:AbsClassB
{
新的公共双顶
{
获得{...}
集合{...}
}

新的公共双底
{
获得{...}
组{...}
}
}

有一个更好的主意是定义一个受保护的虚方法就在 AbsClass ,落实 Top.get Bottom.get 在该方法的条件。然后,你可以直接覆盖法 ConcClassB ,和阴影的属性,而不需要一个额外的类:

 抽象类AbsClass:iCLASS非
{
公共双顶
{
{返回共达(); }
}

公共双底
{
{返回GetBottom(); }
}

保护抽象的双共达();

保护抽象的双GetBottom();
}

类ConcClassB:AbsClass
{
新的公共双顶
{
获得{...}
组{...}
}

新的公共双底
{
获得{...}
组{...}
}

保护覆盖双共达()
{
返回顶部;
}

保护覆盖双GetBottom()
{
回流的底部;
}
}


I have an abstract class, AbsClass that implements an interface, IClass. IClass has a couple properties with only Get accessors. AbsClass implements the properties of IClass as abstract properties to be defined in the classes that derive from AbsClass.

So all of the classes that derive from AbsClass will also need to satisfy IClass by having the same properties with Get accessors. However, in some cases I want to be able to add set accessors to the properties from IClass. Yet if I try to override the abstract properties in AbsClass with a set accessor I get this error

ConcClassA.Bottom.Set cannot override because AbsClass.Bottom does not have an overridable set accessor

See ConcClassA below.

If I have a class that is only implementing the IClass interface, but not inheriting from AbsClass then I am able to add a set accessor with out problems. See ConcClassB below.

I could just implement IClass at each derivation of AbsClass rather then directly for AbsClass. Yet I know from my design that every AbsClass needs to also be an IClass so I'd rather specify that higher up in the hierarchy.

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; }
    }
}


Update

So I think this will make more sense if I explain exactly what I'm trying to do rather then using the abstract example. I work for an Architecture firm and these are business objects related to an architectural design project.

I have an abstract class RhNodeBuilding that represents one type of building on a project. There is some general functionality, like the ability to have floors, that is defined in RhNodeBuilding. RhNodeBuilding also inherits from another abstract classes that allow it be part of a larger project tree structure.

RhNodeBuilding implements from an interface IBuilding which defines a number of read only properties that all buildings should be able to provide such as TopElevation, BottomElevation, Height, NumberOfFloors, etc..etc.. Keep in mind there are other building types that do not derive from RhNodeBuilding, but still need to implement IBuilding.

Right now I have two types that derive from RhNodeBuilding: MassBuilding and FootPrintBuilding. MassBuilding is defined by a 3D shape created by the user. That shape has a TopElevation and a BottomElevation that should be accessible through the corresponding properties, but you shouldn't be able to edit the 3D volume by changing the properties.

FootPrintBuilding on the other hand is defined by a closed curve and a height range to extrude that curve through. So not only should the class be able to return what the current elevations are but these elevations should also be able to be changed to redefine the height range.

So in summary. All buildings (IBuildings) need to be able to return a TopElevation and BottomElevation, but not all buildings should allow TopElevation or BottomElevation to be set directly. All RhNodeBuildings are IBuildings, and classes that derive from RhNodeBuilding may or may not need to be able to directly set TopElevation and 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 { }
    }

}

Right now it seems like the best option is to not have RhNodeBuilding implement IBuilding, but rather have every class that derives from RhNodeBuilding implement IBuilding. That way I can define the properties from IBuilding directly rather then as overrides.

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 {  }
    }
}

解决方案

This works the way it does because properties aren't truly virtual - their accessor methods are. Thus, you cannot override set if there wasn't one in the base class.

What you can do is override and shadow the base class implementation, and provide your own new read/write properties. I don't know of any way to do this without introducing an additional class in the hierarchy:

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 { ... }
    }
}

A better idea would be to define a protected virtual method right in AbsClass, and implement Top.get and Bottom.get in terms of that method. Then you can override that method directly in ConcClassB, and shadow the properties, without the need for an extra class:

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;
    }
}

这篇关于添加一组访问到一个属性,从一个抽象类派生,只有get访问类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆