c#的多台方法,大体上和c++的类似,但是有点区别的,我这里刚刚初学,因此把重点记录下。

多态是同一个行为具有多个不同表现形式或形态的能力。

多态性意味着有多重形式。在面向对象编程范式中,多态性往往表现为"一个接口,多个功能"。

多态性可以是静态的或动态的。在静态多态性中,函数的响应是在编译时发生的。在动态多态性中,函数的响应是在运行时发生的。

在C#中,每个类型都是多态的,因为包括用户定义类型在内的所有类型都继承自Object。

多态就是同一个接口,使用不同的实例而执行不同操作

1、静态多态性

在编译时,函数和对象的连接机制被称为早期绑定,也被称为静态绑定。C#提供了两种技术来实现静态多态性。分别为:

函数重载和运算符重载,运算符重载后续讨论,这里讨论函数重载。英文是overload,和c++的基本类似。

重载有一点是特别注意:不能通过返回值来重载,只能通过函数的参数进行重载。记得在侯捷的视频中,大师提到过,函数名是一样的,但是编译器其实已经做了标记,在底层函数名称是不一样。

函数重载和c++类似,这里不细谈了。总之一点就通过函数参数来重载的。2、动态多态性

2.1抽象类之abstract

C#允许您使用关键字abstract创建抽象类,用于提供接口的部分类的实现。当一个派生类继承自该抽象类时,实现即完成。抽象类包含抽象方法,抽象方法可被派生类实现。派生类具有更具体的功能。

c++也有抽象类,只要定义了纯虚函数的都成为抽象类,纯虚函数:virtual void area() = 0;     //定义纯虚函数,用来某形状计算面积而且不能实例化,只能被继承后,由派生类来实例化。

c#中,也有类似的特性,并且也更加多的特性,有关抽象类的一些规则:

a、您不能创建一个抽象类的实例。

b、您不能在一个抽象类外部声明一个抽象方法。

c、通过在类定义前面放置关键字sealed,可以将类声明为密封类。当一个类被声明为 sealed时,它不能被继承。抽象类不能被声明为 sealed。

抽象类的实例:

using System;
namespace PolymorphismApplication
{
   abstract class Shape        //abstract关键字来定义抽象类
   {
       abstract public int area();
   }
   class Rectangle:  Shape    //继承shape抽象类
   {
      private int length;
      private int width;
      public Rectangle( int a=0, int b=0)
      {
         length = a;
         width = b;
      }
      //public int area() //编译错误
      public override int area ()        //重新做派生类中实现area方法,但要是用override“重写”,否则编译错误
      { 
         Console.WriteLine("Rectangle 类的面积:");
         return (width * length); 
      }
   }    class RectangleTester
   {
      static void Main(string[] args)
      {
         Rectangle r = new Rectangle(10, 7);        //派生类的实例化
         double a = r.area();                        //调用派生类的方法
         Console.WriteLine("面积: {0}",a);
         Console.ReadKey();
      }
   }
}

2.2虚方法之virtual

当有一个定义在类中的函数需要在继承类中实现时,可以使用虚方法。虚方法是使用关键字 virtual声明的。虚方法可以在不同的继承类中有不同的实现。对虚方法的调用是在运行时发生的。

c#的动态多态性是通过 抽象类 和 虚方法 实现的。

以下实例创建了 Shape 基类,并创建派生类 Circle、 Rectangle、Triangle, Shape 类提供一个名为 Draw 的虚拟方法,在每个派生类中重写该方法以绘制该类的指定形状。

虚方法的实例如下:

#define OV      //宏定义一定要放在using前面
/*如果注释掉上面的宏定义,那么程序输出的结果是:  执行基类的画图任务
 执行基类的画图任务
 执行基类的画图任务
 说明,使用new的方法是错误的,与设想的功能偏离了。
 * 说白了,子类调用Draw()的使用是调用了基类的Draw().并没有实现多态的功能
 如果使用上面的宏定义
 输出是
画一个长方形
执行基类的画图任务
画一个三角形
执行基类的画图任务
画一个圆形
执行基类的画图任务
请按任意键继续. . .
 这样就实现了多态。
 * 
 * 这里强调一次:
 * 在子类中用 override 重写父类中用 virtual 申明的虚方法时,
 * 实例化父类调用该方法,执行时调用的是子类中重写的方法;     如果在子类中用 new 覆盖父类中用 virtual 申明的虚方法时,
 * 实例化父类调用该方法,执行时调用的是父类中的虚方法
 * 
 *  override是重写,即将基类的方法在派生类里直接抹去重新写,故而调用的方法就是子类方法;
 *  而new只是将基类的方法在派生类里隐藏起来,故而调用的仍旧是基类方法。
 */ using System;
using System.Collections.Generic; public class Shape
{
    //四个语句没用到
    //public int X { get; private set; }
    //public int Y { get; private set; }
    //public int Height { get; set; }
    //public int Width { get; set; }     // 虚方法
    public virtual void Draw()
    {
        Console.WriteLine("执行基类的画图任务");
    }
} class Circle : Shape
{
#if (OV)
    public override void Draw()     //使用override重写
#else
    public new void Draw()
#endif
    {
        Console.WriteLine("画一个圆形");
        base.Draw();        //调用基类的放大,使用base
    }
}
class Rectangle : Shape
{
#if (OV)
    public override void Draw()     //使用override重写
#else
    public new void Draw()
#endif  
    {
        Console.WriteLine("画一个长方形");
        base.Draw();        //调用基类的放大,使用base
    }
}
class Triangle : Shape
{
#if (OV)
    public override void Draw()     //使用override重写
#else
    public new void Draw()
#endif
    {
        Console.WriteLine("画一个三角形");
        base.Draw();        //调用基类的放大,使用base
    }
} class Program
{
    static void Main(string[] args)
    {
        // 创建一个 List<Shape> 对象,并向该对象添加 Circle、Triangle 和 Rectangle
        var shapes = new List<Shape>
        {
            new Rectangle(),
            new Triangle(),
            new Circle()
        };         // 使用 foreach 循环对该列表的派生类进行循环访问,并对其中的每个 Shape 对象调用 Draw 方法 
        foreach (var shape in shapes)
        {
            shape.Draw();
        }         //Console.WriteLine("按下任意键退出。");
        //Console.ReadKey();
    }
}

在来一个实例:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text; namespace PolymorphismApplication
{
    abstract class Shape        //抽象类
    {
        public abstract int area(); //抽象类的方法,抽象方法只能在抽象类中定义,如果不在抽象类中定义
    }     class Rectangle : Shape     //继承抽象类
    {
        private int length;
        private int width;
        public Rectangle(int a = 0, int b = 0)
        {
            length = a;
            width = b;
        }
        public override int area()  //重写抽象类的方法
        {
            Console.WriteLine("计算长方形类的面积:");
            return (width * length);
        }
    }     class triangle : Shape      //继承抽象类
    {
        private int baseLine;
        private int height;
        public triangle(int a = 0, int b = 0)
        {
            baseLine = a;
            height = b;
        }
        public override int area()  //重写抽象类的方法
        {
            Console.WriteLine("计算三角形类的面积:");
            return (2 * baseLine * height / 4);
        }
    }     class RectangleTester
    {
        static void Main(string[] args)
        {
            Rectangle r = new Rectangle(10, 7); //实例化长方形
            double a = r.area();    //计算长方形的面积
            triangle t = new triangle(10, 7);   //实例化三角形
            double b = t.area();    //计算三角形的面积
            Console.WriteLine("长方形面积: {0}, 三角形面积:{1}", a, b);
            //Console.ReadKey();
        }
    }
}

/*

 运行结果:

 计算长方形类的面积:

计算三角形类的面积:

长方形面积: 70, 三角形面积:35

请按任意键继续. . .

 */

3、总结:

C# 多态性

3.1、多态:一个接口多个功能。

静态多态性:编译时发生函数响应(调用);

动态多态性:运行时发生函数响应。

静态绑定(早期绑定):编译时函数和对象的连接机制。两种技术实现静态多态性:函数重载/运算符重载。

3.2、函数重载:在同一范围内对相同函数名有多个定义,可以是参数类型或参数个数的不同,但不许只有返回值类型不同。

运算符重载,这个后续在讨论。

3.3、关键字 abstract 声明抽象类:用于接口部分类的实现(派生类继承抽象类时,实现完成)。抽象类包含抽象方法,抽象方法可被派生类实现。

抽象类规则:

1.不能创建抽象类的实例

2.不能在抽象类外定义抽象方法

3.不能把抽象类声明为sealed(类前带关键字sealed代表该类是密封类,不能被继承)

4.关键字virtual声明虚方法:用于方法在继承类中的实现(在不同的继承类中有不同的实现)。虚方法也可以被直接调用。

抽象类和虚方法共同实现动态多态性。

注:继承类中的重写虚函数需要声明关键字 override,在方法参数传入中写(类名 形参名)例如 public void CallArea(Shape sh),意思是传入一个 shape 类型的类。

3.4、virtual 和 abstract区别

virtual和abstract都是用来修饰父类的,通过覆盖父类的定义,让子类重新定义。

1.virtual修饰的方法必须有实现(哪怕是仅仅添加一对大括号),而abstract修饰的方法一定不能实现。

2.virtual可以被子类重写,而abstract必须被子类重写。

 3.如果类成员被abstract修饰,则该类前必须添加abstract,因为只有抽象类才可以有抽象方法。

4.无法创建abstract类的实例,只能被继承无法实例化。

5.虚方法也可以被直接调用

3.5、重载和重写区别

重载(overload)是提供了一种机制,相同函数名通过不同的返回值类型以及参数来表来区分的机制。重载在同一个作用域(一般指一个类)的两个或多个方法函数名相同,参数列表不同的方法叫做重载,它们有三个特点(俗称两必须一可以):

a.方法名必须相同

b.参数列表必须不相同

c.返回值类型可以不相同

重写(override)是用于重写基类的虚方法,这样在派生类中提供一个新的方法。

子类中为满足自己的需要来重复定义某个方法的不同实现,需要用 override 关键字,被重写的方法必须是虚方法,用的是 virtual 关键字。它的特点是(三个相同):

相同的方法名

相同的参数列表

相同的返回值

3.6、抽象方法和虚方法的区别

1.虚方法必须有实现部分,抽象方法没有提供实现部分,抽象方法是一种强制派生类覆盖的方法,否则派生类将不能被实例化。这个是特别需要注意的!

 2.抽象方法只能在抽象类中声明,虚方法不是。如果类包含抽象方法,那么该类也是抽象的,也必须声明类是抽象的。这一点好c++是一样的。

 3.抽象方法必须在派生类中重写,这一点和接口类似,虚方法不需要再派生类中重写。简单说,抽象方法是需要子类去实现的。虚方法是已经实现了的,可以被子类覆盖,也可以不覆盖,取决于需求。

抽象方法和虚方法都可以供派生类重写。

c#中的多态学习总结的更多相关文章

  1. PHP中的Libevent学习

    wangbin@2012,1,3 目录 Libevent在php中的应用学习 1.      Libevent介绍 2.      为什么要学习libevent 3.      Php libeven ...

  2. java中实现多态的机制是什么?

    多态性是面向对象程序设计代码重用的一个重要机制,我们曾不只一次的提到Java多态性.在Java运行时多态性:继承和接口的实现一文中,我们曾详细介绍了Java实现运行时多态性的动态方法调度:今天我们再次 ...

  3. 转:C#中的多态

    封装.继承.多态,面向对象的三大特性,前两项理解相对容易,但要理解多态,特别是深入的了解,对于初学者而言可能就会有一定困难了.我一直认为学习OO的最好方法就是结合实践,封装.继承在实际工作中的应用随处 ...

  4. 13、java中的多态

    1,多态的体现 父类的引用指向了自己的子类对象. 父类的引用也可以接收自己的子类对象.2,多态的前提 必须是类与类之间有关系.要么继承,要么实现. 通常还有一个前提:存在覆盖. 3,多态的好处 多态的 ...

  5. C#中区别多态、重载、重写的概念和语法结构

    C#中区别多态.重载.重写的概念和语法结构 重写是指重写基类的方法,在基类中的方法必须有修饰符virtual,而在子类的方法中必须指明override. 格式: 基类中: public virtual ...

  6. 转载:C#中的多态

    原文地址 http://www.cnblogs.com/jhxk/articles/1644018.html  感谢博主分享! 之前看到过类似的问题:如果面试时主考官要求你用一句话来描述多态,尽可能的 ...

  7. JS中childNodes深入学习

    原文:JS中childNodes深入学习 <html xmlns="http://www.w3.org/1999/xhtml"> <head> <ti ...

  8. CNCC2017中的深度学习与跨媒体智能

    CNCC2017中的深度学习与跨媒体智能 转载请注明作者:梦里茶 目录 机器学习与跨媒体智能 传统方法与深度学习 图像分割 小数据集下的深度学习 语音前沿技术 生成模型 基于贝叶斯的视觉信息编解码 珠 ...

  9. c++中虚多态的实现机制

    c++中虚多态的实现机制 參考博客:http://blog.csdn.net/neiloid/article/details/6934135 序言 证明vptr指针存在 无继承 单继承无覆盖 单继承有 ...

随机推荐

  1. 移动端1px边框解决方案

    在retina屏中,像素比为2(iPhone6/7/8)或3(iPhone6Plus/7Plus/8Plus),1px的边框看起来比真的1px更宽. 使用伪类加transform的方式 元素本身不定义 ...

  2. Matlab 非线性规划问题模型代码

    非线性规划问题的基本内容 非线性规划解决的是自变量在一定的非线性约束或线性约束组合条件下,使得非线性目标函数求得最大值或者最小值的问题. 当目标函数为最小值时,上述问题可以写成如下形式: \[ \mi ...

  3. Java学习笔记二——正则表达式

    Java正则表达式 正则表达式的规则 “abc” 匹配字符串abc [abc] 匹配[]里任意一个字符 [a-z]: 匹配所有小写字母中的任意一个字符 [A-Z]: 匹配所有大写字母中的任意一个字符 ...

  4. error adding symbols:DSO missing from command line

    编译时加上-lz,如果是使用eclipse,则在添加库z

  5. 安装nginx1.16.1版本

    安装nginx1.16.1版本 一.添加源 到 cd /etc/yum.repos.d/ 目录下 新建nginx.repo 文件 vim nginx.repo 输入以下信息 [nginx-stable ...

  6. MVC路由规则

    1 可以创建多条路由规则,每条路由规则的那么属性不同 2路由规则是有顺序的.如果被前面的规则匹配了,那么后面的规则就没机会了 3 constraints 约束: 4namespaces 命名空间 5r ...

  7. docker-compose up 启动容器服务超时错误:ERROR: An HTTP request took too long to complete. Retry with --verbose to obtain debug information.

    问题: 本人正在使用docker运行一个中型的项目,包含40多个微服务及相关的docker.由于docker-compose up 同时启动的服务过多,超过了请求HTTP限制的60s时间仍未全部成功启 ...

  8. 3. ABP .NETCore 添加企业微信第三方登录

    1.企业微信登录步骤 1.获取企业微信Token 官方文档:https://work.weixin.qq.com/api/doc#90000/90135/91039 2.通过Token 与前端传的Co ...

  9. Windows下使用MongoDb的经验

    随着NoSql广泛应用MongoDb这个Json数据库现在也被广泛使用,接下来简单介绍一下Windows下如使安装使用MongoDb. 一.安装MongoDb 1.首先去官方网址:(https://w ...

  10. ar 解压一个.a文件报错: xxx.a is a fat file (use libtool(1) or lipo(1) and ar(1) on it)

    Linux  使用终端指令 ar x /Users/apple/Desktop/libWC_LIB_SDKT.a解压一个文件 报错如图所示: 是因为该.a文件包含了多个cpu架构,比如armv7,ar ...