C#本质论6.0第六章:继承

基类型与派生类型之间的转型:

显式转型与隐式转型:

从派生类型转型为基类型称为隐式转型,转型总会成功,不会引发异常。

从基类型转型为派生类型称为显式转型,在转型过程中可能会失败,为了执行显示转型,要在原始引用名称之前,将要转换成的类型放在前面圆括号中。

自定义转换:

不相关的类型之间也能进行相互转换,C#允许类型包含显式与隐式转型转换符,在转型有可能失败时,开发者应定义显式转型操作符。

class GPSCoordinates
{
    //...
    public static implicit operator UTMCoordinates(
        GPSCoordinates coordinates)
    {
        //implicit 隐式转换关键字
        //explicit 显式转换关键字
    }
}

单继承:

一个类不能直接从两个类派生。

在极少数需要多继承结构的时候,一般的解决方案是使用聚合

  • 聚合:一个类包含另一个类的实例。
public class PdaItem
{
    //主要基类
}
public class Person
{
    //字段类
}
public class Contact : PdaItem
{   //派生类
    //持有另一个类的实例
    private Person InternalPerson{get; set;}
    public string FirstName
    {
        get{return InternalPerson.FirstName;}
        set{InternalPerson.FirstName = value;}
    }
    //...
}

缺点:

1. 因委托而增加复杂性。
?   2. 在字段类上新增的任何方法都需要人工添加到派生类中,否则Contact无法公开新增的功能。

密封类:

为了正确设计类,让其他人通过继承来拓展它的功能,需要对它进行全面测试,验证派生能成功的进行。为了避免非预期的派生,并避免出现因此而产生的问题,可以把类标记为sealed

public sealed class CommandLineParser
{
    //...不能从该类派生出其他类
}

基类的重写:

在基类中,必须将允许重写的每个成员标记为virtual,假如一个public或protected成员没有包含virtual修饰符,就不允许子类重写该成员。

public class PdaItem
{
    public virtual string Name{get;set;}
}

public class Contact : PdaItem
{
    public override string Name
    {
        //...
    }
}
  • 对成员进行重载,会造成运行时调用最深的或者说派生的最远的实现。因此,虚方法不应包含关键代码,如果派生类重写了它,那么那些代码将永远得不到调用。不要在构造器中调用会影响所构造对象的任何虚方法,假如这个虚方法在当前要实例化的类型的派生类型中进行了重写,就会调用重写的实现,但在继承层次结构中,字段尚未完全初始化,所以调用虚方法将导致无法预测的行为。
  • 如果没有对虚方法进行重写,编译器会报告警告信息,我们可以通过new关键字来解决该问题:
    • new修饰符在基类面前隐藏了派生类重新声明的成员,这时不是调用派生的最远的成员,相反,是搜索继承链,找到使用new修饰符的那个成员之前的成员,然后调用该成员。如果继承链中仅包含两个类,就会使用基类的成员,感觉就像是派生类没有重写那个成员。
  • 对类使用sealed修饰符可以禁止从该类继承,虚成员也可以密封。一般很少将整个类标记为密封,除非是遇到迫切需要这种限制的情况。
  • base成员:重写成员时,调用该成员的基类版本。
  • override修饰的任何成员都自动成为虚成员。

构造器:

在实例化一个派生类的时候,运行时首先调用基类的构造器,以避免绕过对基类的初始化。假如基类没有可访问的默认构造器,我们需要在派生类构造器的头部显式指定要运行哪一个基类构造器。

public class Contact : PdaItem
{
    public Contact(string name):base(name)
    {
        Name = name;
    }
}

抽象类:

(abstract)抽象类是仅供派生的类,无法实例化抽象类,只能实例化从它派生的类。抽象成员定义了从抽象实体派生的对象应包含什么,但这种成员不包含实现。一个类要从抽象类成功的派生,必须为抽象基类的抽象方法提供具体的实现。

  • 不可实例化只是抽象类的一个较次要的特征,其主要特征是它包含抽象成员,抽象成员是没有实现的方法或属性,其作用是强制所有派生类提供实现。

is&as

  • is操作符可以用来判断基础类型,并非仅仅是检查数据能否成功转型为目标类型,还会检查底层对象本身是否是目标类型,如果不是,返回false
  • as尝试将对象转换成特定数据类型,当不能转换的时候,as操作符会返回null。

原文地址:https://www.cnblogs.com/zhang-mo/p/9834062.html

时间: 2024-10-17 01:52:47

C#本质论6.0第六章:继承的相关文章

《Entity Framework 6 Recipes》中文翻译系列 (30) ------ 第六章 继承与建模高级应用之多对多关联

翻译的初衷以及为什么选择<Entity Framework 6 Recipes>来学习,请看本系列开篇 第六章  继承与建模高级应用 现在,你应该对实体框架中基本的建模有了一定的了解,本章将帮助你解决许多常见的.复杂的建模问题,并解决你可能在现实中遇到的建模问题. 本章以多对多关系开始,这个类型的关系,无论是在现存系统还是新项目的建模中都非常普遍.接下来,我们会了解自引用关系,并探索获取嵌套对象图的各种策略.最后,本章以继承的高级建模和实体条件结束. 6-1  获取多对多关联中的链接表 问题

深入浅出Zabbix 3.0 -- 第六章 监控项配置与管理

第六章 监控项配置与管理 Zabbix系统中监控项(Items)的定义和管理非常重要,所有的监控指标都是通过定义不同的监控项收集数据.Zabbix通过主机作为一个逻辑单元组织和管理监控项,所有的监控项都必须属于某个主机,且在同一主机中只能有一个唯一的监控项存在. 6.1监控数据 Zabbix 不同于与大多数其他监控解决方案的一个重要特征是Zabbix通过监控项从被监控对象收集的数据是原始数据,而不是告警或状态的更新数据.大多数监控方案中,不管是通过agent或其他方法收集到监控数据后,会对该数据

《Entity Framework 6 Recipes》中文翻译系列 (37) ------ 第六章 继承与建模高级应用之独立关联与外键关联

翻译的初衷以及为什么选择<Entity Framework 6 Recipes>来学习,请看本系列开篇 6-13  在基类中应用条件 问题 你想从一个已存在的模型中的实体派生一个新的实体,允许基类被实例化. 解决方案 假设你有如图6-20所示的模型. 图6-20 包含Invoice实体的模型 这个模型只包含一个单独的实体Invoice(发货单).我们想从Invoice派生一个新的实体,它表示删除掉的发货单.这将允许我们以更清晰的业务逻辑来分别对有效的发货单和已删除掉的发货进行不同的操作.按下面

《Entity Framework 6 Recipes》中文翻译系列 (35) ------ 第六章 继承与建模高级应用之TPH继承映射中使用复合条件

翻译的初衷以及为什么选择<Entity Framework 6 Recipes>来学习,请看本系列开篇 6-11  TPH继承映射中使用复合条件 问题 你想使用TPH为一张表建模,建模中使用的复杂条件超过了实框架能直接支持的能力. 解决方案 假设我们有一张Member表,如图6-15所示.Member表描述了我们俱乐部的会员信息.在我们的模型中,我们想使用TPH为派生类,AdultMember(成人会员).SeniorMember(老年人会员)和TeenMember(青少年会员)建模. 图6-

《Entity Framework 6 Recipes》中文翻译系列 (33) ------ 第六章 继承与建模高级应用之TPH与TPT (2)

翻译的初衷以及为什么选择<Entity Framework 6 Recipes>来学习,请看本系列开篇 6-8  嵌套的TPH建模 问题 你想使用超过一层的TPH继承映射为一张表建模. 解决方案 假设你有一张员工(Employee)表,它包含各种类型的员工,比如,钟点工,雇员.如图6-10所示. 图6-10 包含各种类型的员工表 Employee表包含钟点工,雇员,提成员工,这是雇员下面的一个子类型.按下面的步骤,使用派生类型HourlyEmployee,SalariedEmployee和Sa

《Entity Framework 6 Recipes》中文翻译系列 (32) ------ 第六章 继承与建模高级应用之TPH与TPT (1)

翻译的初衷以及为什么选择<Entity Framework 6 Recipes>来学习,请看本系列开篇 6-6  映射派生类中的NULL条件 问题 你的表中,有一列允许为null.你想使用TPH创建一个模型,列值为null时,表示一个派生类型,不为null时,表示另一个派生类型. 解决方案 假设你有一张表,描述医学实验药物.这张表包含一列指示该药是什么时候批准生产的.药在批准生产之前都被认为是实验性的.一但批准生产,它就被认为是药物了.我们就以图6-7中Drug表开始我们这一小节的学习. 图6

《Entity Framework 6 Recipes》中文翻译系列 (36) ------ 第六章 继承与建模高级应用之TPC继承映射

翻译的初衷以及为什么选择<Entity Framework 6 Recipes>来学习,请看本系列开篇 6-12  TPC继承映射建模 问题 你有两张或多张架构和数据类似的表,你想使用TPC继承映射为这些表建模. 解决方案 假设我们有如图6-18所示的表. 图6-18 表Toyota和BMW有相似的结构,它们可以成为派生至实体Car的派生类型 在图6-18中,表Toyota和BMW有相似的架构(Schema),并描述类似的数据.BMW表只多了额外的一列,它用一bit值来指示对应的实例是否具有避

《Entity Framework 6 Recipes》中文翻译系列 (34) ------ 第六章 继承与建模高级应用之多条件与QueryView

翻译的初衷以及为什么选择<Entity Framework 6 Recipes>来学习,请看本系列开篇 6-10  创建一个多条件过滤 问题 你想使用多个条件为实体过滤表中的行. 解决方案 假设你有一张处理网站订单的表,如图6-13所示. 图6-13 表WebOrder包含网站订单的信息 假设我们有这样一个业务需求,WebOrder中的实例为,2012年以后的,2010年到2012年之间未删除的,2010年以前的订单金额大于200美元的.这样的复杂过滤条件不能使用映射详细信息窗口中有限制的条件

C#本质论6.0第五章:类

面向对象编程 封装: 封装的目的是隐藏细节.在必要的时候,细节仍然可以访问,但通过巧妙的封装细节,大的程序变得更容易理解,数据不会因为不慎而被修改,代码也变得更容易维护. 继承: 继承允许在这些相似但又不同的物体之间建立"属于"关系从而得到一个类层次结构.更具体的类型称为派生类型或者子类型,更常规的类型称为基类型或者超类型. 多态性: 多态性意味着一个方法或类型可以具有多种形式的表现.在多态性的帮助下,不同的类型能自己照料一个方法的实现细节,因为共享同一个公共基类型(或接口)的多个派生