不了解虚拟和受保护集的OOP

时间:2013-04-26 17:11:23

标签: c# inheritance

嗨,我以为我理解这些概念,但我不确定了。

假设我有以下内容:

接口

public interface IUnit
{
    DateTime CreatedDateTime { get; set; }
}

基础课程

public abstract class UnitBase : IUnit
{
    public virtual DateTime CreatedDateTime
    {
        get;
        protected set;
    }
    DateTime IUnit.CreatedDateTime
    {
        get
        {
            return CreatedDateTime;
        }
        set
        {
            CreatedDateTime = value;
        }
    }
}

然后,我有另一个继承自UnitBase

的类
public class NewClass : UnitBase
{
}

NewClass包含CreatedDateTime的属性,因为它继承自UnitBase,并且由于NewClass没有覆盖它,我想它仍然具有set的受保护访问器。

所以,如果我要创建一个新的NewClass实例:

NewClass obj = new NewClass();
obj.CreatedDateTime = DateTime.Now;  //This is not allowed 

但为什么我可以将obj转换为IUnit并修改它?

//like this
((IUnit)obj).CreatedDateTime = DateTime.Now  //Allowed?

我认为protected set只能在它声明的类(UnitBase)和从它继承的类(NewClass)的范围内设置它的值。那么为什么我可以投射并修改它呢?如果允许,保护集的重点是什么?我不太明白这里发生了什么。有人可以向我解释一下吗?

编辑:Sry我修改了代码,现在应该编译。那么,如果我能够将它转换为IUnit并更改值,那么这不会破坏受保护集的目的吗?我可以更改界面中的修饰符,这样我就无法转换为IUnit并修改值吗?

3 个答案:

答案 0 :(得分:1)

IUnit接口指定了一个setter。这意味着setter是公共的,这就是允许你通过强制转换为IUnit来设置它的原因。

如果您希望IUnit的实现能够为set指定自己的访问修饰符,只需指定get必须在接口中公开,如下所示:

public interface IUnit
{
    DateTime CreatedDateTime { get; }
}

答案 1 :(得分:0)

如果您将obj转换为IUnitIUnit,编译器会将其视为IUnit,因此您可以设置CreateDateTime和没有什么是错的或特别的。

此外,您的代码将无法编译。因为UnitBase没有实现IUnit。要找到您要找的内容,您可以按以下方式修改UnitBase

public class UnitBase : IUnit
{
    public DateTime CreateDateTime { get; protected set; }

    DateTime IUnit.CreatedDateTime
    {
        get; set;
    }
}

答案 2 :(得分:0)

接口定义了一个合同,该合同表明CreateDateTime具有公共get / set。一旦你转换了该对象,它就会将对象视为接口,并且接口具有公共集。

如果不是这种情况,任何采用IUnit的函数都必须动态确定对象的真实类型,然后查看是否应用了访问修饰符。这意味着静态链接不会在您传入虚拟对象时发生,并且派生的子项可能会更改接口的含义。想想当你谈论单独构建程序集时会有什么意义