C#杂记之陆:真·杂记
注:以下文稿写于2020年,虽未完整,为了不卡杂记的序号,还是发出来了。
日后会在这里添加更多内容,也可能另起一篇拾遗(
这一篇是真正的“杂”记。这段时间在刷LeetCode的同时,阅览了一些Java中常见的问题,鉴于Java与C#的殊途同归,也有了些收获。
为查漏补缺,将之前理解还不够明了的部分记在这里,主要是涉及OOP思想的一些概念。
关于多态
面向对象设计有四大特征:
- 抽象:通过类和接口的属性与方法实现
- 继承:通过类和接口的继承实现
- 封装:通过访问控制符实现
- 多态:???
多态这个概念比较神秘。以前看到一个解释是这么说的:
继承是子类引用父类方法;多态是父类引用子类方法。
当时看了觉得有点奇怪,父类怎么能引用子类方法呢?现在我的理解是如下:
子类对象继承了父类方法,但是可能又对继承过来的父类方法进行了重写覆盖。而一切出现父类的地方都可以用其子类向上转型进行替换(里氏替换原则),调用方法时调用的会是在子类里被重写的子类方法。继承、重写和向上转型,这是实现多态的三要素。
这样,如果一个父类有多个子类,它们又分别用不同方式重写了继承下来的同一个方法,那么在把这些子类都当父类使用时,就会展现出多态性:明明是对同一个类的对象调用了同一个方法,但行为却完全不同。
举个例子,假如有个扬声器类,包含一个大叫()方法,调用时会“嘤嘤嘤”;而继承自它的有大叫“洒↓比↑”的喇叭类和大叫“哼,哼,啊啊啊啊啊啊啊”的野兽先辈类:
//这段代码甚至真的可以跑,C#支持用汉字做标识符,大概是因为用了Unicode
using System;
using System.Collections.Generic;
namespace PlayGround
{
class 扬声器
{
public virtual void 大叫() => Console.WriteLine("嘤嘤嘤");
}
class 喇叭 : 扬声器
{
public override void 大叫() => Console.WriteLine("洒↓比↑");
}
class 野兽先辈 : 扬声器
{
public override void 大叫() => Console.WriteLine("哼,哼,啊啊啊啊啊啊啊");
}
class 屑狐狸 : 扬声器
{
public override void 大叫() => Console.WriteLine("呜呜呜呜,好可怜啊");
}
class Program
{
static void Main(string[] args)
{
var 一堆扬声器 = new List<扬声器>() { new 扬声器(), new 喇叭(), new 野兽先辈(), new 屑狐狸() };
foreach (var 某个扬声器 in 一堆扬声器)
{
某个扬声器.大叫();
// 输出:
// 嘤嘤嘤
// 洒↓比↑
// 哼,哼,啊啊啊啊啊啊啊
// 呜呜呜呜,好可怜啊
}
}
}
}
