C#多态

C#多态

多态性(C# 编程指南)转自MSDN

 

通过继承,一个类可以用作多种类型:可以用作它自己的类型、任何基类型,或者在实现接口时用作任何接口类型。这称为多态性。C# 中的每种类型都是多态的。类型可用作它们自己的类型或用作 Object 实例,因为任何类型都自动将 Object 当作基类型。

多态性不仅对派生类很重要,对基类也很重要。任何情况下,使用基类实际上都可能是在使用已强制转换为基类类型的派生类对象。基类的设计者可以预测到其基类中可能会在派生类中发生更改的方面。例如,表示汽车的基类可能包含这样的行为:当考虑的汽车为小型货车或敞篷汽车时,这些行为将会改变。基类可以将这些类成员标记为虚拟的,从而允许表示敞篷汽车和小型货车的派生类重写该行为。

多态性概述

当派生类从基类继承时,它会获得基类的所有方法、字段、属性和事件。面向对象的语言使用虚方法表达多态。若要更改基类的数据和行为,您有两种选择:可以使用新的派生成员替换基成员,或者可以重写虚拟的基成员。

使用新的派生成员替换基类的成员需要使用 new 关键字。如果基类定义了一个方法、字段或属性,则 new 关键字用于在派生类中创建该方法、字段或属性的新定义。new 关键字放置在要替换的类成员的返回类型之前。例如:

public class BaseClass
 2{
 3    public void DoWork() { }
 4    public int WorkField;
 5    public int WorkProperty
 6    {
 7        get return 0; }
 8    }
 9}
10public class DerivedClass : BaseClass
11{
12    public new void DoWork() { }
13    public new int WorkField;
14    public new int WorkProperty
15    {
16        get return 0; }
17    }
18}
19

使用 new 关键字时,调用的是新的类成员而不是已被替换的基类成员。这些基类成员称为隐藏成员。如果将派生类的实例强制转换为基类的实例,就仍然可以调用隐藏类成员。例如:

DerivedClass B = new DerivedClass();
B.DoWork();  // Calls the new method.

BaseClass A = (BaseClass)B;
A.DoWork();  // Calls the old method.

为了使派生类的实例完全接替来自基类的类成员,基类必须将该成员声明为虚拟的。这是通过在该成员的返回类型之前添加 virtual 关键字来实现的。然后,派生类可以选择使用 override 关键字而不是 new,将基类实现替换为它自己的实现。例如:

public class BaseClass
{
    public virtual void DoWork() { }     
    public virtual int WorkProperty
    {
        get { return 0; }
    }
}
public class DerivedClass : BaseClass
{
    public override void DoWork() { }
    public override int WorkProperty
    {
        get { return 0; }
    }
}

字段不能是虚拟的,只有方法、属性、事件和索引器才可以是虚拟的。当派生类重写某个虚拟成员时,即使该派生类的实例被当作基类的实例访问,也会调用该成员。例如:

DerivedClass B = new DerivedClass();
B.DoWork();  // Calls the new method.

BaseClass A = (BaseClass)B;
A.DoWork();  // Also calls the new method.

使用虚拟方法和属性可以预先计划未来的扩展。由于在调用虚拟成员时不考虑调用方正在使用的类型,所以派生类可以选择完全更改基类的外观行为。

无论在派生类和最初声明虚拟成员的类之间已声明了多少个类,虚拟成员都将永远为虚拟成员。如果类 A 声明了一个虚拟成员,类 B 从 A 派生,类 C 从类 B 派生,则类 C 继承该虚拟成员,并且可以选择重写它,而不管类 B 是否为该成员声明了重写。例如:

public class A
{
    public virtual void DoWork() { }
}
public class B : A
{
    public override void DoWork() { }
}
public class C : B
{
    public override void DoWork() { }
}

派生类可以通过将重写声明为密封的来停止虚拟继承。这需要在类成员声明中将 sealed 关键字放在 override 关键字的前面。例如:

public class C : B
{
    public sealed override void DoWork() { }
}

在上面的示例中,方法 DoWork 对从 C 派生的任何类都不再是虚拟的。它对 C 的实例仍然是虚拟的 -- 即使将这些实例强制转换为类型 B 或类型 A。派生类可以通过使用 new 关键字替换密封的方法,如下面的示例所示:

public class D : C
{
    public new void DoWork() { }
}

在此情况下,如果在 D 中使用类型为 D 的变量调用 DoWork,被调用的将是新的 DoWork如果使用类型为 C、B 或 A 的变量访问 D 的实例,对 DoWork 的调用将遵循虚拟继承的规则,即把这些调用传送到类 C 的 DoWork 实现。

已替换或重写某个方法或属性的派生类仍然可以使用基关键字访问基类的该方法或属性。例如:

public class A
{
    public virtual void DoWork() { }
}
public class B : A
{
    public override void DoWork() { }
}
public class C : B
{
    public override void DoWork()
    {
        // Call DoWork on B to get B's behavior:
        base.DoWork();

        // DoWork behavior specific to C goes here:
        // ...
    }
}

注意

建议虚拟成员在它们自己的实现中使用 base 来调用该成员的基类实现。允许基类行为发生使得派生类能够集中精力实现特定于派生类的行为。未调用基类实现时,由派生类负责使它们的行为与基类的行为兼容。

转载于:https://www.cnblogs.com/opop/p/5552771.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/257075.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Ubuntu 14.04.02 安装openvswitch-2.3.1

Open vSwitch安装 安装好操作系统 # lsb_release -a LSB Version: core-2.0-amd64:core-2.0-noarch:core-3.0-amd64:core-3.0-noarch:core-3.1-amd64:core-3.1-noarch:core-3.2-amd64:core-3.2-noarch:core-4.0-amd64:core-4.0-noarch:core-4.1-amd64:core-4.1-noarch:security…

struts-上传

一、创建项目项目名称:demoupload二、添加jar包commons-fileupload-1.2.2.jarcommons-io-2.0.1.jarcommons-lang3-3.1.jarfreemarker-2.3.19.jarjavassist-3.11.0.GA.jarognl-3.0.5.jarstruts2-core-2.3.4.1.jarxwork-core-2.3.4.1.jar三、在web.xml文件中配置过滤器…

将数组作为参数,调用该函数时候给的是数组地址还是整个数组

1、在实际的应用中,数组经常作为函数参数,将数组中的数据传递到另外一个函数中,一般来说,传递可以采用两种方法: 1>、数组元素作为函数的实参时,用法跟普通变量作参数相同,将数组元素的值传递…

C#项目中常用到的设计模式

C#项目中常用到的设计模式 1. 引言 一个项目的通常都是从Demo开始,不断为项目添加新的功能以及重构,也许刚开始的时候代码显得非常凌乱,毫无设计可言。但是随着项目的迭代,往往需要将很多相同功能的代码抽取出来,这也是…

学习笔记(14):Python网络编程并发编程-文件传输功能实现

立即学习:https://edu.csdn.net/course/play/24458/296245?utm_sourceblogtoedu 1.课程目的: 实现客户端输入下载文件的命令,然后将命令发送给服务端,服务端再执行下载文件的命令,最后将执行下载文件命令后的结果返回给客户端&a…

NFS精简版配置方法

此实验的前提是防火墙需关闭。 1.关闭iptables /etc/init.d/iptables stop /etc/init.d/iptables status 2.关闭selinux setenforce 0 getenforce Permissive ---出现这个单词即代表selinux临时关闭,如需永久关闭则需修改/etc/sysconfig/selinux配置文件 …

Serializable接口中serialVersionUID字段的作用

序列化运行时使用一个称为 serialVersionUID 的版本号与每个可序列化类相关联,该序列号在反序列化过程中用于验证序列化对象的发送者和接收者是否为该对象加载了与序列化兼容的类。 如果接收者加载的该对象的类的 serialVersionUID 与对应的发送者的类的版本号不同&…

重新认知指针

1、把指针指向的变量的数据类型称为指针的数据类型;而任何一个指针变量本身数据值的类型都是unsigned long int 2.、指针变量名前的符号“*”表示的是指向运算。 3、不要认为“ *p" 是指针变量,指针变量是p而不是*p 4、

分布式数据库 HBase

原文地址:http://www.oschina.net/p/hbase/ HBase 概念 HBase – Hadoop Database,是一个高可靠性、高性能、面向列、可伸缩的分布式存储系统,利用HBase技术可在廉价PC Server上搭建起大规模结构化存储集群。 HBase是Google Bigtable的开源实…

学习笔记(15):Python网络编程并发编程-进程理论

立即学习:https://edu.csdn.net/course/play/24458/296423?utm_sourceblogtoedu 1.进程:正在运行的一个过程或者一个任务; 2.进程与程序的区别:程序是一堆代码,程序运行起来就是进程了,一个程序运行两次,算…

【翻译】Designing Websites for iPhone X

让网站适配 iphone X 英文原文地址:https://webkit.org/blog/7929/...本文原文地址:https://github.com/cnsnake11/... The section below about safe area insets was updated on Oct 31, 2017 to reflect changes in the iOS 11.2 beta. 以下关于safe …

指针作为函数参数引用数组的任意元素

void swap(int *a,int*b) {*a*a^*b;*b*a^*b;*a*a^*b; } swap(data[j],data[j1]); int data[10]{13,55,48,13,62,45,754,0,10};以上是我遇到的问题,我觉得调用这个swap函数是不能这样直接把数组的某个元素直接丢给swap数据 在程序中参加数据处理的量不是指…

使用 Log4Net 记录日志

第一步:下载Log4Net 下载地址:http://logging.apache.org/log4net/download_log4net.cgi 把下载的 log4net-1.2.11-bin-newkey解压后,如下图所示: 双击bin文件夹 双击net文件夹,选择针对.NET FramerWork的不同版本 找…

Xcode常用快捷键

1. 文件CMD N: 新文件CMD SHIFT N: 新项目CMD O: 打开CMD S: 保存CMDOPtS:保存所有文件CMD SHIFT S: 另存为CMD W: 关闭窗口CMD Q :退出XcodeCMD SHIFT W: 关闭文件2. 编辑CMD [: 左缩进CMD ]: 右缩进CMDshiftF:项目中查找CMDG:查找下一个CMDshiftG:查…

学习笔记(16):Python网络编程并发编程-开启子进程的两种方式

立即学习:https://edu.csdn.net/course/play/24458/296424?utm_sourceblogtoedu #方式一:使用python内置模块multiprocessing下的process类 from multiprocessing import Process import time#定义进程函数 def task(name):print(%s is running!%name)t…

ElasticSearch的API python调用

os json datetime datetime django.http HttpResponse reelasticsearch Elasticsearches Elasticsearch([])res8 es.search({:{:{:{::}}}} ) statistic():():hit res8[][]:a (%hit %hit[])a re.split(a);arow a:id row[] row[]idHttpResponse(a)转载于:https://blog.51cto…

HDU 1757 A Simple Math Problem (矩阵快速幂)

题目链接&#xff1a;http://acm.hdu.edu.cn/showproblem.php?pid1757 在吴神的帮助下才明白如何构造矩阵&#xff0c;还是好弱啊。 此处盗一张图 1 #include <iostream>2 #include <cstdio>3 #include <cstring>4 #include <cmath>5 #include <al…

Spring学习使用标签来标记资源(@Component、@Repository、 @Service和@Controller)和用法(包括如何jsp正在使用)...

首先&#xff0c;在xml其中新增部分标有下划线的文件&#xff0c;容器初始化的时候需要扫描包 注意&#xff1a; a. 包款扫描(下划线部分)一定要加&#xff0c;默认是不扫描整个包。与每一包之间’&#xff0c;’开。如过具有同样的父包&#xff0c;那么我们能够用父包来取…

python 判断字符串时是否是json格式方法

在实际工作中&#xff0c;有时候需要对判断字符串是否为合法的json格式 解决方法使用json.loads,这样更加符合‘Pythonic’写法 代码示例&#xff1a; Python import json def is_json(myjson):try:json_object json.loads(myjson)except ValueError, e:return Falsereturn Tr…