C#之继承实现

目录
  • 一.继承的类型
    • 1.实现继承和接口继承
    • 2.多重继承
    • 3.结构的继承
  • 二.继承的实现
    • 1.虚方法
    • 2.隐藏方法
    • 3.调用函数的基类版本
    • 4.抽象类和抽象函数
    • 5.密封类和密封方法
    • 6.派生类的构造函数
  • 三. 修饰符
    • 1.可见性修饰符
    • 2.其它修饰符
  • 四.接口

一.继承的类型

在面向对象的编程中,有两种截然不同继承类型:实现继承和接口继承

1.实现继承和接口继承

*实现继承:表示一个类型派生于基类型,它拥有该基类型的所有成员字段和函数。在实现继承中,派生类型采用基类型的每个函数的实现代码,除非在派生类型的定义中指定某个函数的实现代码。在需要给现有的类型添加功能,或许多相关的类型共享一组重要的公共功能时,可以使用这种类型的继承。
*接口继承:表示一个类型只继承了函数的签名,没有继承任何的代码。在需要指定该类型具有某些可用的特性时,最好使用这种类型的继承。

2.多重继承

C#不支持多重继承,但C#允许类型派生自多个接口————多重接口继承。这说明,C#类可以派生自另一个类和任意多个接口。更准确的说,因为System.Object是一个公共的基类,所以每个C#(除Object之外)都有一个基类,还可以有任意多个接口。

3.结构的继承

使用结构的一个限制是结构不支持实现继承,但每个结构都自动派生自System.ValueType。不能编码实现类型层次的结构,但结构可以实现接口。

二.继承的实现

语法:

  class MyDreved:BaseClass
  {

  }

如果类或结构也派生自接口,则用逗号分隔列表中的基类和接口:

  class MyDreved:BaseClass,IIntenface1,IIntenface2
  {

  }

如果在类定义中没有指定基类,C#编译器就假定System.Object是基类。

1.虚方法

把一个基类函数声明为virtual,就可以在任何派生类中重写(override)该函数:

  class BaseClass
  {
    public virtual void VirtualMethod()
    {
      //
    }
  }

也可以把属性声明为virtual。对于虚属性或重写属性,语法与非虚属性相同,但要在定义中添加virtual关键字:

  public virtual string Name
  {
    get;set;
  }

C#中虚函数的概念与标准OOP的概念相同:可以在派生类中重写虚函数。在调用方法时,会调用该派生类的合适方法。在C#中,函数默认情况下不是虚的,但(除了构造函数)可以显式的声明为virtual。
在派生类中重写一个函数时,要使用override关键字显示声明:

  class MyDreved: BaseClass
  {
    public override void VirtualMethod()
    {
      //
    }
  }

成员字段和静态函数都不能声明为virtual,因为这个概念只对类中的实例函数成员有意义。

2.隐藏方法

如果签名相同的方法在基类和派生类中都进行了声明,但该方法没有分别声明为virtual和override,派生类方法就会隐藏基类方法。

class A
{
    public void a()
    {
      Console.WriteLine('CLASS is A');
    }
}

class B:A
{
    public void a()
    {
       Console.WriteLine('CLASS is B');
    }
}

class client
{
    static void main()
    {
        B b=new B();
       A a=b;

       a.a();
          b.a();
    }
}

/*输出
CLASS IS A
CLASS IS B
*/

在大多数情况下,是要重写方法,而不是隐藏方法,因为隐藏方法会造成对于给定类的实例调用错误的方法。但是,C#语法会在编译时收到这个潜在错误的警告。
在C#中,要隐藏一个方法应使用new 关键字声明,这样在编译时就不会发出警告:

  class A
  {
    public void a()
    {
      Console.WriteLine('CLASS is A');
    }
  }

  class B:A
  {
    public new void a()
    {
       Console.WriteLine('CLASS is B');
    }
  }

3.调用函数的基类版本

C#可以从派生类中调用方法的基本版本:base.<MethodName>()

  class MyDreved: BaseClass
  {
    public override void VirtualMethod()
    {
      base.VirtualMethod();
    }
  }

可以使用base.<MethodName>()语法调用基类中的任何方法,不必从同一方法的重载中调用它。

4.抽象类和抽象函数

C#允许把类和函数声明为abstract.抽象类不能实例化,而抽象不能直接实现,必须在非抽象的派生类中重写。显然抽象函数也是虚拟的(尽管不需要提供virtual,实际上,也不能提供该关键字)。
如果类包含抽象函数,则该类也是抽象的,也必须声明为抽象的:

  abstract class Building
  {
    public abstract void Cal();
  }

抽象类中不能声明非抽象方法,但可以声明其它的非抽象成员。

5.密封类和密封方法

C#允许把类和方法声明为sealed。对于类,这表示不能继承该类;对于方法,表示不能重写该方法。

  sealed class A
  {

  }

  class B:A //报错
  {

  }

如果基类上不希望有重写的方法和属性,就不要把它声明为virtual.

6.派生类的构造函数

假定没有为任何类定义任何显示的构造函数,编译器就会为所有的类提供默认的初始化构造函数,在后台编译器可以很好的解决类的层次结构中的问题,每个类中的每个字段都会初始化为对应的默认值。
在创建派生类的实例时,实际上会有多个构造函数起作用。要实例化的类的构造函数本身不能初始化类,还必须调用基类中的构造函数。
构造函数的调用顺序是先调用Object,在按照层次结构调用基类的构造函数,由基类到父类,直到到达要实例化的类为止。在这个过程中,每个构造函数都初始化它自己的类中的字段。因为最先调用的总是基类的构造函数,所以派生类在执行过程中可以访问任何基类的成员,因为基类已经构造出来了,其字段也初始化了。

  • *在层次结构中添加无参数的构造函数 在层次结构中添加一个无参数的构造函数会替换默认的构造函数,所以在执行过程中,会默认调用基类中添加的无参数的构造函数。其它方面不变。
  • *在层次结构中添加带参数的构造函数 在层次结构中要调用这个带参数的构造函数,需要在父类的构造函数中显示调用:
public abstract class GenericCustomer
{
    private string name;

    public GenericCustomer()
    {
        name = "<no name>";
    }

    public GenericCustomer(string name)
    {
        this.name = name;
    }

    public string Name
    {
        get {return name;}
        set {name = value;}
    }

}

public class Nevermore60Customer : GenericCustomer
{
    private string referrerName;
    private uint highCostMinutesUsed;

    ublic Nevermore60Customer(string name) : this(name, "            <None>")
    {
    }

    public Nevermore60Customer(string name, string referrerName) : base(name)
    {
        this.referrerName = referrerName;
    }

    public string ReferrerName
    {
        get {return referrerName;}
         set {referrerName = value;}
    }

}

三. 修饰符

修饰符可以指定方法的可见性:如public或private,还可以指定一项的本质,如方法是virtual或abstract.

1.可见性修饰符

修饰符 应用于 说明
public 所有类和成员 任何代码可以访问
protected 类的成员和内嵌类 只有在类内部和派生类中访问
internal 所有类和成员 只有在类内部和包含它的程序集中访问
private 类的成员和内嵌类 只有在类内部访问
protected internal 类的成员和内嵌类 只有在类内部,派生类中和包含它的程序集中访问

不能把类定义为protected,private,protected internal,因为这些修饰符对于包含在名称空间中的类型没有意义。因此这些修饰符只能应用于成员。但是可以用这些修饰符定义嵌套的类(内嵌类,包含在其它类中的类),因为在这种情况下,类也具有成员的状态:

  public class OuterClass
  {
    protected class InnerClass
    {

    }
  }

2.其它修饰符

修饰符 应用于 说明
new 函数 隐藏函数
static 所有成员 静态
virtual 函数 成员可以由派生类重写
abstract 类,函数 抽象
override 函数 重写虚拟和抽象的成员
sealed 类,方法,属性 不能继承和重写
extern 仅静态方法 成员在外部用另一种语言实现

四.接口

  public interface IDisposable
  {
    void Dispose();
  }

声明接口在语法上和声明抽象类完全相同,但不允许提供任何成员的实现方式。抽象类可以提供除方法之外的其它成员的实现方式,比如属性。
一般情况下,接口只能包含方法,属性,索引器和事件的声明。
不能实例化接口,接口即不能有构造函数,也不能有字段。接口定义也不允许包含运算符重载。
在接口中不允许声明关于成员的修饰符。接口成员总是公有的,不能声明为虚拟和静态。如果需要,在实现的类中声明。
实现接口的类必须实现接口的所有成员。
接口可以彼此继承,其方式与类的继承方式相同。

到此这篇关于C#之继承实现的文章就介绍到这了。希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • c#继承中的函数调用实例

    本文实例讲述了c#继承中的函数调用方法,分享给大家供大家参考.具体分析如下: 首先看下面的代码: 复制代码 代码如下: using System;   namespace Test {     public class Base     {         public void Print()         {             Console.WriteLine(Operate(8, 4));         }           protected virtual int Ope

  • C#中事件的继承实例分析

    通常来说,C#中的子类无法调用父类的事件,但是可以通过在父类中创建一个方法来调用父类的事件,而子类通过调用父类的方法来触发事件. 具体实现代码如下: class parent { protected string name; public event Handle OnEvent; protected SendEvent(HandleArgs args) { if (OnEvent != null) { OnEvent(this, args); } } } class clild : paren

  • C#中的类继承详解

    目录 前言 类的继承 注意事项 寄语 总结 前言 在日常的程序编码工作中,我们的最终目标是完成公司交给自己的开发任务,核心目标是写出好代码. 那么什么是好代码? 高内聚,低耦合 想必从事编码工作的我们,基本都听说过这句话.那么什么样的代码是高内聚,又如何低耦合呢. 今天咱们就来了解下在C#这个高级语言中,是通过那些形式来表现的. 在目前的高级语言中,这三个特点是共通的,也是我们日常编码中要经常使用的.就是封装.继承.多态. 我们先来看看继承 类的继承 通过继承我们可以得到一个新的类,新类可以自己

  • c#继承与多态使用示例

    继承和多态 派生类具有基类所有非私有数据和行为以及新类自己定义的所有其他数据或行为,即子类具有两个有效类型:子类的类型和它继承的基类的类型. 对象可以表示多个类型的能力称为多态性. 多态性示例 复制代码 代码如下: public class Parent    {        public Parent() { }        public void MethodA()        {            Console.WriteLine("调用MethodA()");   

  • 浅谈C# 类的继承

    继承 一个类可以继承自另一个类.在 C#中,类与类之间只存在单一继承.也就是说,一个类的直接基类只能有一个.当类与类之间实现继承的时候,子类可以将它的直接基类的所有成员当做自己的成员,除了类的静态构造方法.实例构造方法和析构方法.但是,虽然基类的所有成员都可以当做子类的成员,但是如果基类的成员设置了不同的访问权限,则派生类可以访问的成员也随之不同.C#的继承是可以传递的,如果类C从类B派生,而类B从类A派生,则类C将继类B的所有成员,也继承类A的所有成员(各个基类的静态构造方法.实例构造方法和析

  • 深入理解C#之继承

    目录 C#之继承 能够阻止某个类被其他类继承吗? 那么我们该如何获得基类的构造函数和自身的构造函数呢? 都定义有构造函数时,那么执行顺序会怎样呢? 总结 C#之继承 继承.封装和多态是面向对象编程的重要特性. 其成员被继承的类叫基类也称父类,继承其成员的类叫派生类也称子类. 派生类隐式获得基类的除构造函数和析构函数以外的所有成员.派生类只能有一个直接基类,所以C#并不支持多重继承,但一个基类可以有多个直接派生类. 继承是可以传递的. 即:如果 ClassB 派生出 ClassC,ClassA 派

  • C#中实现多继承的方法

    近日看到了一个贴子,就是在C#语言中,如何实现多继承的问题.相信涉猎c#不多的人(像我这样的菜鸟),一看就觉得很可笑,c#肯定是不能实现多继承的啊.都知道在c++中因为实现多继承会有很多的歧义问题,所以在c#中就把多继承给取消了,而用接口来实现!但是想想,如果是初学者肯定不会不会问这样的问题.肯定是个高手,然后就开始上网查资料!然后发现真的可以实现! 说起多继承,首先大家可以想想这个问题:你知道在C#中怎么实现多继承吗? 主流的答案无非2种. 答案一:用接口啊,一个类可以继承自多个接口的. 答案

  • c# 继承快速入门

    在面向对象当中继承是非常重要的,也是面向对象的三大特性之一(继承.封装.多态),今天我们来揭开他的神秘面纱. 话不多说,我们上菜. using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; /** * 假设我们公司有两种程序员: * java程序员指的是用java语法写程序的程序员,用Jpro这个类表示: * C#程序员指的

  • 深入分析c# 继承

    继承是面向对象程序设计中最重要的概念之一.继承允许我们根据一个类来定义另一个类,这使得创建和维护应用程序变得更容易.同时也有利于重用代码和节省开发时间. 当创建一个类时,程序员不需要完全重新编写新的数据成员和成员函数,只需要设计一个新的类,继承了已有的类的成员即可.这个已有的类被称为的基类,这个新的类被称为派生类. 继承的思想实现了 属于(IS-A) 关系.例如,哺乳动物 属于(IS-A) 动物,狗 属于(IS-A) 哺乳动物,因此狗 属于(IS-A) 动物. 基类和派生类 一个类可以派生自多个

  • 不错的一篇关于javascript-prototype继承

    1.最基本的用法 把ClassA的一个实例赋值给ClassB, ClassB就继承了ClassA的所有属性. 代码入下: function ClassA() { this.a='a'; } function ClassB() { this.b='b'; } ClassB.prototype=new ClassA(); var objB=new ClassB(); for(var p in objB)document.write(p+" "); [Ctrl+A 全选 注:如需引入外部Js

  • JavaScript面向对象之Prototypes和继承

    一.前言 本文翻译自微软的牛人Scott Allen Prototypes and Inheritance in JavaScript ,本文对到底什么是Prototype和为什么通过Prototype能实现继承做了详细的分析和阐述,是理解JS OO 的佳作之一.翻译不好的地方望大家修改补充. 二.正文 JavaScript中的面向对象不同于其他语言,在学习前最好忘掉你所熟知的面向对象的概念.JS中的OO更强大.更值得讨论(arguably).更灵活. 1.类和对象 JS从传统观点来说是面向对象

  • javascript类式继承新的尝试

    我今天做的尝试是,如何更它更像其他的语言一样的使用继承机制,多层继承和更方面的调用父类的构造. 我希望达到的效果: 复制代码 代码如下: function A(){ alert('a'); } function B(){ this.$supClass(); alert('b'); } extend(B,A); function C(){ this.$supClass(); alert('c'); } extend(C,B); var c = new C(); alert( c instanceo

  • JavaScript 原型继承

    Object.prototype JavaScript是基于原型继承的,任何对象都有一个prototype属性.Object.prototype是所有对象的根,并且不可改变. 复制代码 代码如下: Object.prototype=null; alert(Object.prototype);//[object Object] Object与Object.prototype Object继承于Object.prototype,增加一个属性给Object.prototype上,同时也会反应到Obje

  • Javascript面向对象编程(三) 非构造函数的继承

    今天是最后一个部分,介绍不使用构造函数实现"继承". 一.什么是"非构造函数"的继承? 比如,现在有一个对象,叫做"中国人". 复制代码 代码如下: var Chinese = { nation:'中国' }; 还有一个对象,叫做"医生". 复制代码 代码如下: var Doctor ={ career:'医生' } 请问怎样才能让"医生"去继承"中国人",也就是说,我怎样才能生成一个&

  • Javascript面向对象编程(二) 构造函数的继承

    今天要介绍的是,如何生成一个"继承"多个对象的实例. 比如,现在有一个"动物"对象的构造函数, 复制代码 代码如下: function Animal(){ this.species = "动物"; } 还有一个"猫"对象的构造函数, 复制代码 代码如下: function Cat(name,color){ this.name = name; this.color = color; } 怎样才能使"猫"继承&

  • JS继承 笔记

    JS继承 JavaScript中没有类的概念,与类相关的继承的概念更是无从谈起,但是我们可以通过特殊的语法来 模拟面向对象语言中的继承. 在JS中模拟继承有多种方式,其中寄生组合模式是一种比较容易简单的模拟继承模式,下面我们就来 介绍一下用寄生组合模式模拟继承. JS的继承包括属性的继承和方法的继承,他们分别通过不同的方法来实现. 1属性的继承 属性的继承通过改变函数的执行环境来实现的.而改变函数的执行环境可以使用call()和apply()两种 方法来实现. 我们首先创建一个Animal"类&

  • JavaScript 继承使用分析

    深入学习javascript继承之前,先了解下面的几个概念: 父类:被继承的类 子类:由继承得来的类 超类:也就是父类 抽象类:一般不用来实例化的类,它的用途是用来给其他类继承. 基类:提供给其他类可以继承的类 派生类:由基类继承而来的类 javascript对象继承通常有下面的5种方式: 1.对象冒充 2.call()方式 3.apply()方式 4.原型链 5.混合方式 A.对象冒充 所谓对象冒充,就是新的类冒充旧的类(旧的类必须采用构造函数方式),从而达到继承目的. eg.1 复制代码 代

  • Javascript面向对象之四 继承

    复制代码 代码如下: var JsObject = {} || new Object(); JsObject.extend = function(subClass, superClass){ //先判断子类subClass是否已经定义,如果未定义,则重新定义类. if(typeof subClass == "undefined")subClass = function(){}; //如果父类superClass是类,则转化成对象 if(typeof superClass == &quo

  • AngularJS深入探讨scope,继承结构,事件系统和生命周期

    本文实例讲述了AngularJS的scope,继承结构,事件系统和生命周期.分享给大家供大家参考,具体如下: 深入探讨 Scope 作用域 每一个 $scope 都是类 Scope 的一个实例.类 Scope 拥有可以控制 scope 生命周期的方法,提供事件传播的能力,并支持模板渲染. 作用域的层次结构 让我们再来看看这个简单的 HelloCtrl 的例子: var HelloCtrl = function($scope){ $scope.name = 'World'; } HelloCtrl

随机推荐