当前位置: 首页 > wzjs >正文

wordpress制作侧面悬浮图标秦洁婷seo博客

wordpress制作侧面悬浮图标,秦洁婷seo博客,春雨app直播免费看,网络服务商缩写目录 引言 一、开篇:程序员的变形魔法 二、多态的本质解析 1. 官方定义背后的深意 2. 现实世界的多态映射 三、C#实现多态的核心武器:虚方法体系 1. virtual:开启重写之门 2. override:改写父类行为 3. base:…

目录

引言

一、开篇:程序员的变形魔法

二、多态的本质解析

1. 官方定义背后的深意

2. 现实世界的多态映射

三、C#实现多态的核心武器:虚方法体系

1. virtual:开启重写之门

2. override:改写父类行为

3. base:访问父类版本

4. new:隐藏父类方法

核心差异速记表

1. 基础用法三部曲

 2. 进阶技巧:多层继承中的多态

3. 方法隐藏的注意事项

四、虚方法表(vtable):多态的底层心脏

1. 生活中的vtable比喻

 2. vtable的创建过程

3. 方法调用的寻址过程(快递比喻)

五、示例:智能家居控制系统

六、常见误区深度解析

1. 构造函数中的虚方法陷阱

2. 隐藏方法的误用后果

总结

终极对比表


引言

        在C#的世界中,多态如同程序员手中的"变形术",让一段代码能化身千万形态。你是否曾因满屏的if-else类型判断而焦头烂额?是否渴望让代码像乐高积木般灵活组装?本文将带你穿透virtualoverridebase的迷雾,揭示多态背后的虚方法表(vtable)运作机制,通过智能家居控制等实战案例,教你用多态重构条件分支的"代码腐味",让对象在运行时自如切换形态。这里没有枯燥的理论堆砌,只有从内存布局到设计哲学的深度解构——是时候让你的代码拥有真正的"超能力"了!

一、开篇:程序员的变形魔法

        想象你正在开发一个动物园管理系统。当需要让不同的动物发出叫声时,没有多态的代码会是这样:

if (animal is Dog)((Dog)animal).Bark();
else if (animal is Cat)((Cat)animal).Meow();
// ...

而具备多态能力的代码只需:

animal.MakeSound();

        这就是多态的魅力!让我们揭开这个面向对象编程(OOP)核心概念的神秘面纱。

二、多态的本质解析

1. 官方定义背后的深意

        多态(Polymorphism)源自希腊语"poly"(多)+"morph"(形态),即同一操作作用于不同对象时,可以产生不同的执行结果。这是面向对象三大特性(封装、继承、多态)中最具艺术性的特性。

2. 现实世界的多态映射

  • 打印机:同一份文档在激光/喷墨/3D打印机呈现不同效果

  • 交通系统:不同交通工具的加速方式(汽车加油门 vs 飞机开加力)

  • 游戏技能:同一技能按钮根据角色职业产生不同效果

三、C#实现多态的核心武器:虚方法体系

必备知识:四剑客:virtual/override/base/new

1. virtual:开启重写之门

  • 作用:标记方法可被子类覆盖

  • 代码表现:父类方法前添加virtual

  • 示例

public class Animal {public virtual void MakeSound() { /* 基础实现 */ }
}

2. override:改写父类行为

  • 作用:子类替换父类虚方法的实现

  • 代码表现:子类方法前添加override

  • 示例

public class Dog : Animal {public override void MakeSound() { /* 新的叫声实现 */ }
}

3. base:访问父类版本

  • 作用:在子类中调用父类被重写的方法

  • 代码表现base.方法名()

  • 示例

public class Dog : Animal {public override void MakeSound() {base.MakeSound(); // 先执行父类实现// 添加新功能}
}

4. new:隐藏父类方法

  • 作用:在子类中创建同名新方法(不会覆盖父类方法)

  • 代码表现:子类方法前添加new

  • 示例

public class Cat : Animal {public new void MakeSound() { /* 完全独立的新方法 */ }
}

核心差异速记表

关键字是否修改父类方法是否影响多态典型使用场景
virtual不修改开启多态父类定义可扩展的方法
override完全替换影响子类改变父类方法行为
base不修改不影响子类扩展父类方法
new不修改不影响子类定义与父类同名的新方法

 一句话总结:
virtual 开门,override 改造,base 回访,new 另建。

示例:

public class BaseClass
{// virtual:开启多态之门public virtual void Show(){Console.WriteLine("Base Show");}
}public class DerivedClass : BaseClass
{// override:改写父类实现public override void Show(){// base:访问父类版本base.Show(); Console.WriteLine("Derived Show");}
}public class ShadowClass : BaseClass
{// new:隐藏父类方法public new void Show(){Console.WriteLine("New Show");}
}//测试
BaseClass obj1 = new DerivedClass();
obj1.Show(); 
// 输出:
// Base Show
// Derived ShowBaseClass obj2 = new ShadowClass();
obj2.Show(); 
// 输出:Base ShowShadowClass obj3 = new ShadowClass();
obj3.Show();  
// 输出:New Show

小结:

  • override修改了虚方法表的原始条目

  • new创建了新的独立条目,父类条目仍然存在

  • 编译时类型决定访问哪个虚表条目

至于这个虚方法表是什么,请你接着往下看!答案就在后面哦,现在先记住 

记忆口诀:

Virtual 是门票,Override 改面貌
Base 能回老版本,New 是另起炉灶

对照表:

关键字作用域虚表影响典型场景
virtual父类方法创建虚表条目设计可扩展的方法
override子类方法覆盖父类虚表条目实现多态行为变化
base子类内部无直接影响扩展而非完全替换父类实现
new子类方法创建新虚表条目完全隐藏不兼容的父类方法

1. 基础用法三部曲

public class Animal
{// Step1: 声明虚方法public virtual void MakeSound() {Console.WriteLine("Animal sound");}
}public class Dog : Animal
{// Step2: 使用override重写public override void MakeSound(){Console.WriteLine("Woof!");base.MakeSound(); // Step3: 可选调用基类实现}
}// 使用演示
Animal myPet = new Dog();
myPet.MakeSound(); // 输出"Woof!"和"Animal sound"

 2. 进阶技巧:多层继承中的多态

public class WolfDog : Dog
{public override void MakeSound(){Console.WriteLine("Awoooo!");base.MakeSound(); // 调用Dog类的实现}
}// 运行时表现
Animal wildAnimal = new WolfDog();
wildAnimal.MakeSound(); 
// 输出顺序:
// Awoooo!
// Woof!
// Animal sound

3. 方法隐藏的注意事项

public class Cat : Animal
{// 使用new关键字隐藏基类方法public new void MakeSound(){Console.WriteLine("Meow!");}
}// 使用差异
Animal pet1 = new Cat();
pet1.MakeSound();  // 调用Animal的实现Cat pet2 = new Cat();
pet2.MakeSound();   // 调用Cat的新方法

四、虚方法表(vtable):多态的底层心脏

想象你在驾驶一辆汽车时,按下同一个"加速"按钮:

  • 燃油车会提升发动机转速

  • 电动车会增加电机功率

  • 混合动力车会智能分配两种动力

        看似相同的操作,背后却是完全不同的实现——这正是多态的魔力。但计算机如何知道在运行时该执行哪个具体的方法?答案就藏在**虚方法表(vtable)**这个"导航系统"中。

vtable的作用本质
充当方法的动态路由表,让程序在运行时能:
1️⃣ 自动匹配对象的真实类型
2️⃣ 精准跳转到对应的方法实现
3️⃣ 无缝衔接继承链中的方法版本

        就像GPS根据实时位置规划路线,vtable会根据对象的实际类型,在内存中找到正确的方法入口。没有它,多态就像没有地图的旅行——只能通过大量的if-else手动导航,既笨重又低效。其实就是让你找到哪一个类型应该执行哪个类型自己的方法。

1. 生活中的vtable比喻

想象你去一家餐厅点餐:

  • 普通方法:直接找厨师(固定地址)

  • 虚方法:查看菜单(vtable)找到对应菜品

每个继承层次就像不同的菜单版本:

基础菜单(Animal类):
[0] 叫声方法 -> 默认实现升级菜单(Dog类):
[0] 叫声方法 -> Woof! 
[1] 其他方法 -> 继承基类

 2. vtable的创建过程

// 当创建Dog对象时:
Dog myDog = new Dog();// 内存中的结构:
[对象头]|- 类型指针 → Dog类型信息|- vtable指针 → Dog的虚方法表// Dog的虚方法表:
[0] MakeSound → Dog.MakeSound()  // 重写的方法
[1] ToString  → Animal.ToString() // 继承的方法
[2] GetHashCode → Object.GetHashCode() // 继承的方法

        当你的子类重写方法时,其实就是修改了自己的虚方法表,也就是说你将你自己,继承于父类的同名函数,变成了你自己类型的独门,就和父类没啥关系了,若是你想使用父类的该同名函数,只能通过base使用。 但是只有override才可以,new 只是创建了一个新方法。这个new之后的同名函数,只和你的类型有关了,是哪种类型,便会调用哪种类型里面的该函数。

3. 方法调用的寻址过程(快递比喻)

当执行 animal.MakeSound()

  1. 查快递单号:通过对象头找到类型信息(类似查看快递目的地)

  2. 找分拣中心:定位到vtable(类似快递区域分拣中心)

  3. 派送包裹:根据方法索引找到具体实现(类似最后一公里配送)

 4. 三层蛋糕模型理解继承

顶层蛋糕(Object类)|- vtable[0]: ToString|- vtable[1]: GetHashCode中间层(Animal类)|- vtable[0]: MakeSound(新增)|- 继承Object的vtable[1-...]底层(Dog类)|- vtable[0]: MakeSound(覆盖)|- 继承Animal的vtable[1-...]

五、示例:智能家居控制系统

// 基类定义:抽象设备
public class Device
{// 虚方法:获取设备状态(默认实现返回未知)public virtual string GetStatus(){return "Unknown status";}// 虚方法:执行控制命令(基类实现记录日志)public virtual void ExecuteCommand(string command){Console.WriteLine($"Base command: {command}");}
}// 温度控制器子类
public class Thermostat : Device
{private int _temperature = 20; // 私有状态字段// 重写状态获取方法public override string GetStatus(){// 返回格式化温度值return $"Current temperature: {_temperature}°C";}// 重写命令执行方法public override void ExecuteCommand(string command){// 尝试解析温度数值命令if (int.TryParse(command, out int temp)){_temperature = temp;Console.WriteLine($"Temperature set to {temp}°C");}else{// 调用基类实现处理未知命令base.ExecuteCommand(command);}}
}// 照明设备子类
public class Light : Device
{private bool _isOn; // 开关状态public override string GetStatus(){// 返回当前灯光状态return _isOn ? "Light is ON" : "Light is OFF";}public override void ExecuteCommand(string command){switch(command.ToLower()){case "on":_isOn = true;break;case "off":_isOn = false;break;}// 打印最新状态Console.WriteLine($"Light state: {GetStatus()}");}
}// 使用示例
List<Device> smartHome = new List<Device>
{new Thermostat(), // 添加温度控制器new Light()       // 添加照明设备
};foreach (var device in smartHome)
{// 多态调用GetStatusConsole.WriteLine(device.GetStatus());// 多态执行控制命令device.ExecuteCommand("toggle");
}

六、常见误区深度解析

1. 构造函数中的虚方法陷阱

public class BaseDevice
{public BaseDevice(){/* 危险操作:在基类构造函数中调用虚方法* 此时子类构造函数尚未执行* 子类重写的方法可能访问未初始化的字段 */Initialize();}public virtual void Initialize(){Console.WriteLine("Base initialization");}
}public class SmartLock : BaseDevice
{private string _config; // 子类特有字段public SmartLock(){/* 子类构造函数在基类构造函数之后执行* 此时_config尚未初始化 */_config = LoadConfig();}public override void Initialize(){/* 此处访问_config将得到null!* 因为基类构造函数先于子类执行 */Console.WriteLine($"Using config: {_config}");}private string LoadConfig() => "default.cfg";
}// 当执行 new SmartLock() 时:
// 1. 先执行BaseDevice构造函数
// 2. 调用Initialize()时子类字段未初始化
// 3. 导致NullReferenceException
  • 当基类构造函数调用虚方法时,实际调用的是子类重写的方法

  • 此时子类构造函数尚未执行,_config字段未被初始化

  • 导致输出中_config为空字符串(string默认值)

  • 根本原因:

  • 对象构造顺序:基类构造函数 → 子类字段初始化 → 子类构造函数

  • 多态调用在对象未完全构造时已生效

2. 隐藏方法的误用后果

public class Parent
{public void ShowInfo() => Console.WriteLine("Parent");
}public class Child : Parent
{/* 使用new关键字隐藏而非重写* 这会导致多态行为不符合预期 */public new void ShowInfo() => Console.WriteLine("Child");
}// 测试代码
Parent obj = new Child();
obj.ShowInfo();  // 输出"Parent"而不是"Child"
/* 解释:* 1. 编译时类型为Parent* 2. 调用非虚方法时使用编译时类型的方法* 3. 隐藏方法不会修改vtable中的方法指针 */

补充: new方法如何影响虚方法表?

public class Parent
{public virtual void Method() => Console.WriteLine("Parent");
}public class Child : Parent
{public new void Method() => Console.WriteLine("Child");
}// 测试代码
Parent obj = new Child();
obj.Method();  // 输出"Parent"
((Child)obj).Method(); // 输出"Child"

虚方法表内存模型:

Parent类型虚表:
[0] Method -> Parent.Method()Child类型虚表:
[0] Method -> Parent.Method()  // 未覆盖父类方法
[1] Method -> Child.Method()   // 新增方法(独立条目)

关键结论:

  • new方法不会覆盖虚方法表的父类条目

  • 通过父类引用访问时,始终使用虚表中父类的方法指针

  • 只有通过子类引用才会访问新方法

  • new的本质是隐藏而非覆盖,与编译时类型绑定

总结

        多态是面向对象编程皇冠上的明珠,它通过虚方法体系实现了"一个接口,多种实现"的哲学。从vtable的内存布局到智能家居的实战应用,我们见证了类型系统如何优雅地处理多样性。记住:多态不是银弹,深度继承需要克制,明确设计意图才能发挥其真正威力。当你能在代码中看到"动物叫"的统一接口背后跳动的不同心脏时,就真正掌握了面向对象的精髓。     

终极对比表

特性overridenew
多态性支持(运行时绑定)不支持(编译时绑定)
方法关系是父类方法的特化与父类方法无关的新方法
虚表影响覆盖父类条目新增独立条目
类型兼容子类可替代父类破坏里氏替换原则
适用场景"is-a"关系的扩展意外重名时的临时解决方案

   

http://www.dtcms.com/wzjs/54464.html

相关文章:

  • 网站整站程序我想学做互联网怎么入手
  • 百度糯米网站怎么做奶盘seo伪原创工具
  • 永久免费crm软件哪个好海阳seo排名
  • 做的好点的外贸网站有哪些整合营销传播策略
  • 模板建站小程序怎样弄一个自己的平台
  • 武汉seo公司排名seopeix
  • 昌吉哪个公司做网站全网营销系统怎么样
  • 深圳网站建设价钱湖南 seo
  • 湖北营销型网站建设怎么做品牌推广和宣传
  • 西安长安网站建设制作凡科建站下载
  • 郑州专业建网站百度sem竞价托管公司
  • 保定公司做网站2345浏览器影视大全
  • 可以做公众号背景图的网站网络营销薪酬公司
  • 辽宁省工程建设信息网官网宁波seo网站推广软件
  • 佛山设计网站设计价格最新新闻事件今天国内大事
  • 软件开发标准seo优化的网站
  • 网站整体策划与设计40个免费靠谱网站
  • ecshop 做企业网站搜索引擎调词工具
  • 新公司做网站有效果吗媒体公关公司
  • 专业的电商网站建设公司搜索引擎优化实训报告
  • 湖北做网站系统哪家好江苏免费关键词排名外包
  • wordpress增加导航深圳seo推广培训
  • 下列属于b2b网站的有知乎推广合作
  • 做淘宝客网站再靠地推青岛谷歌优化公司
  • 广州网站建设哪家比较好营销型网站建设费用
  • 网站建设的意见seo的优化方向
  • 360做企业网站多少钱爱站官网
  • 网站前nav是什么意思百度热搜 百度指数
  • 网站平台建设什么意思广州seo教程
  • 专做奢侈品品牌的网站成都网站推广公司