c#重写和多态
多态是基于重写的
- 继承:向子类中添加父类没有的成员,子类对父类的横向扩展
- 重写:纵向扩展,成员没有增加,但成员的版本增加了
引言
Rider
JetBrains:Rider、ReSharper、dotPeek
Rider 支持包括 .NET Core 在内的较全面的 .NET 开发,以及 Unity 开发。
.NET Core / ASP.NETWeb Application 开发包括:
- RestFul API
- .NET Core 网站开发
Q:Rider 是否支持 WinForm 开发?
A:不支持 WinForm,但支持基于 XAML 的 WPF 和 Xamarin
Java 常用 Spring + Hibernate + JPA 这一套,它们都能在 .NET Core 找到对应选择。
ASP.NET Core 框架 + Entity Framework Core
.NET Core 自带 Razor engine
Edx Timothy 参与开发的课程
校长关于 ASP.NET Core 开发的一些课程,分别讲 LINQ、Web 开发基础、RestFul API、实战。
未来还将有一门 ASP.NET Core 高级开发和 Authentication & Authorization。

DFS 与 BFS
- DFS:Depth-First-Search 深度优先搜索
- BFS:Breadth-First Search 广度优先搜索
using System;
using System.Collections.Generic;
using System.Linq; namespace ConsoleTemp
{
// 注:为了方便理解,很多变量命名都用的全称
class Program
{
static void Main(string[] args)
{
// 生成 [0,10) 的自然数数组,即 0,1,2,3...9
var values = Enumerable.Range(0, 10).ToArray();
var binarySearchTree = GetTree(values, 0, values.Length - 1);
DFS(binarySearchTree);
Console.WriteLine("============================");
BFS(binarySearchTree);
} static Node GetTree(int[] values, int lowIndex, int highIndex)
{
if (lowIndex > highIndex) return null;
var middleIndex = lowIndex + (highIndex - lowIndex) / 2;
var node = new Node(values[middleIndex]);
node.Left = GetTree(values, lowIndex, middleIndex - 1);
node.Right = GetTree(values, middleIndex + 1, highIndex);
return node;
} static void DFS(Node node)
{
if (node == null) return;
DFS(node.Left);
Console.WriteLine(node.Value);
DFS(node.Right);
} static void BFS(Node root)
{
var q = new Queue<Node>();
q.Enqueue(root);
while (q.Count > 0)
{
var node = q.Dequeue();
Console.WriteLine(node.Value);
if (node.Left != null) q.Enqueue(node.Left);
if (node.Right != null) q.Enqueue(node.Right);
}
}
} class Node
{
public int Value { get; set; } public Node Left { get; set; } public Node Right { get; set; } public Node(int value)
{
Value = value;
}
}
}

C# 语言标准文档
C# 5.0 已经成为国际标准 ECMA-334,ECMA-334 的 PDF 比微软自己的标准文档还要权威。
C# 6.0 7.0 还在 ECMA 验证中。
笔者注:校长还是很注重标准文档,推荐有志于深入 C# 的同学去多翻一翻、读一读。
下面开始讲解本节的正式内容:
本节内容
- 类的继承
- 类成员的“横向扩展”(成员越来越多)
- 类成员的“纵向扩展”(行为改变,版本增高)
- 类成员的隐藏(不常用)
- 重写与隐藏的发生条件:函数成员,可见,签名一致
- 多态(polymorphism)
- 基于重写机制(virtual -> override)
- 函数成员的具体行为(版本)由对象决定
- 回顾:C# 语言的变量和对象都是有类型的,所以会有“代差”
Override 重写
子类对父类成员的重写。
因为类成员个数还是那么多,只是更新版本,所以又称为纵向扩展。
注:重写时,Car 里面只有一个版本的 Run。
重写需要父类成员标记为 virtual,子类成员标记 override。
注:被标记为 override 的成员,隐含也是 virtual 的,可以继续被重写。
virtual:可被重写的、名义上的、名存实亡的
class Program
{
static void Main(string[] args)
{
var car = new Car();
car.Run();
// Car is running! var v = new Vehicle();
v.Run();
// I'm running!
}
} class Vehicle
{
public virtual void Run()
{
Console.WriteLine("I'm running!");
}
} class Car : Vehicle
{
public override void Run()
{
Console.WriteLine("Car is running!");
}
}
Hide
如果子类和父类中函数成员签名相同,但又没标记 virtual 和 override,称为 hide 隐藏。

这会导致 Car 类里面有两个 Run 方法,一个是从 Vehicle 继承的 base.Run(),一个是自己声明的 this.Run()。
可以理解为 v 作为 Vehicle 类型,它本来应该顺着继承链往下(一直到 Car)找 Run 的具体实现,但由于 Car 没有 Override,所以它找不下去,只能调用 Vehicle 里面的 Run。
class Program
{
static void Main(string[] args)
{
Vehicle v = new Car();
v.Run();
// I'm running!
}
} class Vehicle
{
public void Run()
{
Console.WriteLine("I'm running!");
}
} class Car : Vehicle
{
public void Run()
{
Console.WriteLine("Car is running!");
}
}
注:
- 新手不必过于纠结 Override 和 Hide 的区分、关联。因为原则上是不推荐用 Hide 的。很多时候甚至会视 Hide 为一种错误
- Java 里面是天然重写,不必加 virtual 和 override,也没有 Hide 这种情况
- Java 里面的 @Override(annotation)只起到辅助检查重写是否有效的功能
Polymorphism 多态
C# 支持用父类类型的变量引用子类类型的实例。
函数成员的具体行为(版本)由对象决定。
回顾:因为 C# 语言的变量和对象都是有类型的,就导致存在变量类型与对象类型不一致的情况,所以会有“代差”。
class Program
{
static void Main(string[] args)
{
Vehicle v = new RaceCar();
v.Run();
// Race car is running! Car c = new RaceCar();
c.Run();
// Race car is running! Console.ReadKey();
}
} class Vehicle
{
public virtual void Run()
{
Console.WriteLine("I'm running!");
}
} class Car : Vehicle
{
public override void Run()
{
Console.WriteLine("Car is running!");
}
} class RaceCar : Car
{
public override void Run()
{
Console.WriteLine("Race car is running!");
}
}
C# vs Python
Python 是对象有类型,变量没有类型的语言,Python 变量的类型永远跟着对象走。 所以在 Python 中即使重写了,也没有多态的效果。

PS:
- JS 和 Python 类似,也是对象有类型,变量没类型
- TypeScript 是基于 JS 的强类型语言,所以 TS 变量是有类型的,存在多态
重写三条件
函数成员
只有函数成员才能重写,最常用的是重写 Methods 和 Properties。
函数成员的定义:

重写属性示例:
class Program
{
static void Main(string[] args)
{
Vehicle v = new Car();
v.Run();
// "Car is running!"
Console.WriteLine(v.Speed);
// 50
}
} class Vehicle
{
private int _speed; public virtual int Speed
{
get { return _speed; }
set { _speed = value; }
} public virtual void Run()
{
Console.WriteLine("I'm running!");
_speed = 100;
}
} class Car : Vehicle
{
private int _rpm; public override int Speed
{
get { return _rpm / 100; }
set { _rpm = value * 100; }
} public override void Run()
{
Console.WriteLine("Car is running!");
_rpm = 5000;
}
}
可见
只有对子类可见的父类成员可以重写,具体说就是 protected 和 public。例如子类能继承父类 private 的成员,但无法访问,即不可见、不可重写。
访问级别的更多内容参考 https://www.yuque.com/yuejiangliu/dotnet/timothy-csharp-024-025#c75846f4。
签名一致
方法签名:方法名称 + 类型形参的个数 + 每个形参(从左往右)的类型和种类(值、引用或输出)。
注:下面要讲接口和抽象类,为了与本节内容混淆,必须把本节彻底消化吸收。
c#重写和多态的更多相关文章
- C#和Java的类、继承、重写与多态
面向对象的三大特性是封装.继承.多态,C#和Java都是面向对象的语言所以他们的类.继承.重写与多态有很多共同点,但是实现上也存在一定的区别.其中Java中其实没有虚函数的概念,也可以认为Java的函 ...
- static关键字续、继承、重写、多态
static关键字 1.对于实例变量,每个java对象都拥有自己的一份,存储在堆内存当中,在构造方法执行的时候初始化. 2.所有对象都拥有同一个属性时,并且值相同,建议声明为static变量. 3.静 ...
- oc语言学习之基础知识点介绍(四):方法的重写、多态以及self、super的介绍
一.方法重写 /* 重写:当子类继承了父类的方法时,如果觉得父类的方法不适合,那么可以对这个方法进行重新实现,那么这个就重写. 注意:也就是说,一定只能发生在父类和子类关系中. 然后是子类重新实现父类 ...
- java的方法重写 ,多态和关键字 instanceof和final
package cn.pen; /*final 是一个java的关键字,用于修饰局部变量.属性.方法.类,表示最终的意思. final修饰类表示最终类,无法被继承.public final class ...
- java 继承、重载、重写与多态
首先是java 继承.重载和重写的概念 继承: 继承的作用在于代码的复用.由于继承意味着父类的所有方法亦可在子类中使用,所以发给父类的消息亦可发给衍生类.如果Person类中有一个eat方法,那么St ...
- Java ——重写、多态、抽象类
本节重点思维导图 重写 子类覆盖父类同名的方法 final关键字:不可变的 public static final PAGE_SIZE = 18; final修饰的类不能做为父类被子类继承. 多态 多 ...
- 重载与重写、多态——java
方法的重写(Overriding)和重载(Overloading)是java多态性的不同表现,重写是父类与子类之间多态性的一种表现,重载可以理解成多态的具体表现形式. (1)方法重载是一个类中定义了多 ...
- PHP面相对象编程-重载、覆盖(重写) 多态、接口
http://www.ctolib.com/topics-21262.html http://cnn237111.blog.51cto.com/2359144/1284085 http://blog. ...
- [java核心技术01]__继承与多态、重载与重写、抽象类与接口
前言 前面简单学习了面向对象的知识,知道了其两个重要的特性,继承与多态,今天就围绕着面向对象的这两个特性,将继承与多态及相关的几个几个定义重载与重写,抽象类与接口的相关知识具体学习一下. 类的继承 关 ...
随机推荐
- SampleNet: Differentiable Point Cloud Sampling
Abstract 经典的采样方法(FPS)之类的没有考虑到下游任务. 改组上一篇工作没有解决不可微性,而是提供了变通的方法. 本文提出了解决不可微性的方法 可微松弛点云采样,近似采样点作为一个混合点在 ...
- wayne编译支持k8s1.16+
GitHub: https://github.com/Qihoo360/wayne 文档: 由于wayne 官方文档链接已经失效了,我们可以通过这里查看 wayne 文档, 除了这个地方,我们询问之前 ...
- nim_duilib(7)之TreeView
introduction 更多控件用法,请参考 here 和 源码. 本文的代码基于这里 xml文件添加代码 基于上一篇, 继续向basic.xml中添加下面关于TreeView的代码. xml完整源 ...
- 【LeetCode】349. Intersection of Two Arrays 解题报告(Java & Python)
作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 方法一:Java解法,HashSet 方法二:Pyt ...
- 【九度OJ】题目1473:二进制数 解题报告
[九度OJ]题目1473:二进制数 解题报告 标签(空格分隔): 九度OJ http://ac.jobdu.com/problem.php?pid=1473 题目描述: 大家都知道,数据在计算机里中存 ...
- Now冥想:崩溃服务和性能服务助力提升应用质量
想就像心灵的"健身房",当遇到失眠或情绪问题时,我们可以通过冥想,抚平情绪波澜,享受放松时刻.<Now冥想>正是一款专注冥想与心理健康的应用.它基于国际先进的正念冥想理 ...
- Java 将Excel转为OFD
OFD是一种开放版式文档(Open Fixed-layout Document )的英文缩写,是我国国家版式文档格式标准.本文,通过Java后端程序代码展示如何将Excel转为OFD格式.方法步骤如下 ...
- Bean拷贝工具
Apache BeanUtils Spring BeanUtils cglib BeanCopier Hutool BeanUtil Mapstruct Dozer 1.Apache BeanUti ...
- 定义制造业操作(定义 MES/MOM 系统)
定义制造业操作(定义 MES/MOM 系统) 制造业操作包含众多工厂级活动,涉及设备(定义.使用.时间表和维护).材料(识别.属性.位置和状态).人员(资格.可用性和时间表),以及这些资源与包含其信息 ...
- 【算法】01-数据结构概述(注意区分jvm堆与堆/jvm栈与栈)
[算法]01-数据结构概述(注意区分jvm堆与堆/jvm栈与栈) 欢迎关注b站账号/公众号[六边形战士夏宁],一个要把各项指标拉满的男人.该文章已在github目录收录. 屏幕前的大帅比和大漂亮如果有 ...