[英]Beginner: Extending a class in C#, am I doing it wrong?
同样, 免责声明免责声明通常仍在学习C#和OOP,所以希望您对我耐心:)
我目前正在使用一个具有FileVersion
类的CMS,该类基本上包含与文件有关的属性列表,例如文件名,文件类型,字节大小,id,上载日期,最新版本等。
FileVersion
的列表包含在具有自己唯一ID的File
中。 当您要从CMS下载特定文件时,将使用以下内容构建URL:
string URL = "/files/"+file.id.toString()+"/"+file.fileVersion.Last().filename;
现在,对于我正在处理的特定控件(专门处理作为文档的文件),能够将URL与所有其他FileVersion
信息一起存储以备后用是很有意义的。 因此,我决定要做的是创建自己的名为DocumentVersion
的类,该类扩展了FileVersion
。 看起来是这样的:
public partial class DocumentVersion : FileVersion
{
public DocumentVersion() : base() { }
public string link;
}
现在我应该注意,看来我不需要在这里实现接口了-但是不要以为福音,这就是为什么我在这里。
但是,当我尝试将FileVersion
为DocumentVersion
如下所示:
DocumentVersion dv = ((DocumentVersion)fileversion);
我得到以下异常:
无法将类型为“ Foo.CMS.FileVersion”的对象转换为类型为“ CoA.DocumentVersion”的对象。
我的暗示是,因为我试图在与原始位置不同的命名空间中扩展类,但是就像我说的那样,OOP对我而言相对较新,所以我可能是错的。
在此先感谢您的帮助。 这个社区是如此宝贵! 我只是希望一旦我变得更加熟练,我就可以回馈:)。
您是否要垂头丧气? 即采用现有的FileVersion
并将其声明为DocumentVersion
?
如果是这样,您将无法执行此操作,因为您所拥有的不过是FileVersion
。
相反,您需要创建一个新的 DocumentVersion
对象。 您的DocumentVersion
构造函数将采用FileVersion
所需的参数,然后通过base()
调用FileVersion
构造函数。
请注意,如果您有一个现有的FileVersion
对象,则可能需要一个对象来包装它,而不是从中派生一个对象。 例如,您的DocumentVersion
不会派生自FileVersion
,而是包含对FileVersion
的私有引用,以及根据需要的其他数据。 在这种情况下,这可能更合适。
例如(按OO术语,这是组成 )
public class DocumentVersion {
private FileVersion fv;
private String url;
public DocumentVersion(FileVersion fv, String url) {
this.fv = fv;
this.url = url;
}
}
有关合成的更多信息,请参见此处 。
您不能将FileVersion
为DocumentVersion
因为您的fileversion变量包含FileVersion,而不是DocumentVersion。 继承是指:
如果对象是作为FileVersion创建的,则只是FileVersion。 期。 如果它是作为DocumentVersion创建的,则可以在使用FileVersion的任何地方使用它(请参阅上面的规则1), 并且可以使用它的DocumentVersion功能。
因此,在创建 FileVersion对象时,您需要创建一个DocumentVersion代替(如果您可以控制代码的这一部分),则强制转换将起作用。 这些DocumentVersions可以与FileVersions存储在同一列表中,因为每个DocumentVersion也是FileVersion。
编辑:由于上述两个规则对于理解OO原理至关重要,因此让我用一个示例进行说明:DocumentVersion = dog和FileVersion = animal。 那么上述规则将是:(1)每只狗都是动物,但(2)并非每只动物都是狗。 因此,您可以创建动物列表,在其中存储所有种类的动物(狗,猫,只是“动物”的东西,...),但是您不能将动物类型的变量强制转换为狗,除非在已经创建为狗(或作为狮子狗(类狮子狗:犬),它是由规则狗 (1))。
用面向对象的术语:如果将狗存储在动物类型的变量中,则对象的静态类型为“动物”, 动态类型为“狗”。 如果元素的动态类型是T或其子类型,则只能将其转换为T类型。
您不能让父亲( FileVersion
)扮演儿子( DocumentVersion
)的角色。
反之亦然=>您可以让儿子当父亲。
(FileVersion)documentVersion //有效
(DocumentVersion)fileVersion //无效(因为fileVersion无法知道派生类型具有的内容)
这就是OOP的基础知识。
DocumentVersion dv = null;
if (fileversion is DocumentVersion)
{
dv = fileversion as DocumentVersion;
}
(正如大多数答案所言,您无法回退FileVersion
不知道什么是DocumentVersion
)。
解决该问题的一种方法是在DocumentVersion
的构造函数中复制字段
public partial class DocumentVersion : FileVersion
{
public DocumentVersion() : base() { }
public DocumentVersion(FileVersion version) : this()
{
this.id = version.id;
// etc.
}
public string Link { get;set; }
}
或在DocumentVersion
上创建一个静态方法,该方法从您提供的FileVersion
返回一个DocumentVersion
,例如:
public static void New(FileVersion version)
{
this.id = version.id;
// etc.
}
提到的另一种技术是合成。 您将FileVersion
作为属性存储在DocumentVersion
public class DocumentVersion
{
public FileVersion FileVersion { get;set; }
public string Link { get;set; }
}
由于您不能将FileVersion
转换为DocumentVersion
而您所需要做的就是添加获取URL的方法,因此您可以创建采用FileVersion
的扩展方法 :
public static string GetLink(this FileVersion fileVersion) {
return "/files/"+fileVersion.id.ToString()+"/"+fileVersion.FileVersion.Last().Filename
}
注意:仅当使用C#3.0时,此方法才有效。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.