深入浅出OOP(一): 多态和继承(早期绑定/编译时多态)
在本系列中,我们以CodeProject上比较火的OOP系列博客为主,进行OOP深入浅出展现。
无论作为软件设计的高手、或者菜鸟,对于架构设计而言,均需要多次重构、取舍,以有利于整个软件项目的健康构建,有些经验是前辈总结的,我们拿来使用即可,有些是团队知识沉淀的,总之复用前人好的思想有利于减少返工。当然,在面试的时候,如果能围绕OOP大谈特谈,自然会加分多多的。
开始阅读本系列博客的预备知识,多态、封装、面向对象编程等,请通过MSDN学习。如下图的术语,您应该耳熟能详的。本系列文章使用C#作为唯一脚本语言。
OOP
1 是什么OOP,以及OOP的优势是什么?
OOP代表的是面向对象编程(Object-Oriented Programming),它基于对象的整体进行编程,取代了基于过程函数的编程思想。具体实现是围绕对象进行数据、函数封装,而不是基于逻辑关系。OOP中的对象直达的是一个特定的类型、或者某类型的实例对象、更多时候是一个class。每个class对象的结构基本相似,但是有各自特有的属性和数据值。对象之间可通过对外的接口进行访问:方法、属性等。基于OOP的这些优势,独立的对象可以修改而不会影响到其他对象,这样会比较方便的升级软件减少潜在的bug。软件系统随着时间的推移,会变得越来越大,OOP编程思想有效的提高了系统代码的可读性和管理性。
2 OOP的概念是什么?
下面用5个术语来说明OOP的具体概念是什么:
数据抽象(Data Abstraction):数据抽象是对需要操作的物体进行建模的出发点,既对使用对象进行了抽象,隐藏了内部的细节(对使用的最终用户而言)。用户可以非常方便的使用class的方法、数据,而不用关心数据创建、运行逻辑的背后复杂的过程。我们以真实世界为例,当你骑一辆自行车的时候,不用考虑变速齿轮的原理如何驱动链条、车轮吧。
继承(Inheritance):继承是OOP概念中最流行的一个概念。继承给程序员提供了可复用代码的优势。基类定义好函数逻辑,子类通过继承,可实现直接访问--就想子类自身的方法一样方便。
数据封装(Data Encapsulation):对class的成员变量、成员函数通过访问控制符进行包装,则称为数据封装。访问控制符有public、Protected、Private、Internal 4种类型。
多态(Polymorphism):对象可通过传递不同参数实现相同的动作,这种行为我们称之为多态。我们以真实世界为例,“开车”这个方法,对不同类型的用户要提供不同的参数实现多态,如Car.Drive(Man), Car.Drive(Woman)等。
消息通信(Message Communication):消息通信意味着通过通过消息进行class函数的调用、执行。
3 多态(Polymorphism)
在本节,我们分别用代码片段来阐述各自类型的多态类型:函数重载、早期绑定、编译器的多态。
先创建一个console 工程,并命名为InheritanceAndPolymorphism,然后添加类Overload.cs,再添加
DisplayOverload函数。
public class Overload{ public void DisplayOverload(int a){System.Console.WriteLine("DisplayOverload " + a);} public void DisplayOverload(string a){System.Console.WriteLine("DisplayOverload " + a);} public void DisplayOverload(string a, int b){System.Console.WriteLine("DisplayOverload " + a + b);}}
在Program.cs添加如下代码:
class Program{ static void Main(string[] args){Overload overload = new Overload();overload.DisplayOverload(100);overload.DisplayOverload("method overloading");overload.DisplayOverload("method overloading", 100);Console.ReadKey();
运行程序,结果如下:
DisplayOverload 100
DisplayOverload method overloading
DisplayOverload method overloading100
Overload类中的
DisplayOverload提供了3类不同的重载函数:方法名相同,参数类型和个数不同。C#中的这种方式成为重载,既我们不需要为每类函数定义不同名字的函数,仅需要改变函数参数类型和个数即可实现,这个也成为函数签名。
用不同的返回值可以否? 我们试试下面的代码:
public void DisplayOverload() { }public int DisplayOverload(){ }
肯定的结果是,Visual Studio会给予如下的报错信息:
Error: Type 'InheritanceAndPolymorphism.Overload' already defines a member called 'DisplayOverload' with the same parameter types
从上面的结果可知:返回值不作为多态函数签名。
我们再运行如下的代码:
static void DisplayOverload(int a) { }public void DisplayOverload(int a) { }public void DisplayOverload(string a){ }
结果依然是报错:
Error: Type 'InheritanceAndPolymorphism.Overload' already defines a member called 'DisplayOverload' with the same parameter types
结论:static的可见函数修饰符不作为重载签名。
运行下面的代码,试试out、ref可否作为重载签名。
private void DisplayOverload(int a) { }private void DisplayOverload(out int a){a = 100;}private void DisplayOverload(ref int a) { }
结果是如下的报错:
Error: Cannot define overloaded method 'DisplayOverload' because it differs from another method only on ref and out
结论:ref、out传递参数修饰符也不能作为重载签名。
4 多态中Params 参数的作用
一个函数可包含如下4种类型的参数传递:
值传递 (pass by value)
引用传递 (Pass by reference)
作为output参数 (As an output parameter)
使用参数数组 (Using parameter arrays)
我们运行如下代码:
public void DisplayOverload(int a, string a) { } public void Display(int a){ string a;}
不出意外,获得如下报错信息:
Error1: The parameter name 'a' is a duplicate
Error2: A local variable named 'a' cannot be declared in this scope because it would give a different meaning to 'a', which is already used in a 'parent or current' scope to denote something else
在相同的作用域中,参数名称必须是唯一的。
在Overload.cs文件中,添加如下代码:
public class Overload{ private string name = "Akhil"; public void Display(){Display2(ref name, ref name);System.Console.WriteLine(name);} private void Display2(ref string x, ref string y){System.Console.WriteLine(name);x = "Akhil 1";System.Console.WriteLine(name);y = "Akhil 2";System.Console.WriteLine(name);name = "Akhil 3";}}
在Program.cs中添加如下代码:
class Program{ static void Main(string[] args){Overload overload = new Overload();overload.Display();Console.ReadKey();}}
运行结果如下:
Akhil
Akhil 1
Akhil 2
Akhil3
结论:我们通过ref引用传递了name的内存地址,故修改x、y的值相当于直接修改name的值,故结果运行如上。
下面这段代码演示了params关键字的作用:
在Overload.cs文件添加如下代码:
public class Overload{ public void Display(){DisplayOverload(100, "Akhil", "Mittal", "OOP");DisplayOverload(200, "Akhil");DisplayOverload(300);} private void DisplayOverload(int a, params string[] parameterArray){ foreach (string str in parameterArray)Console.WriteLine(str + " " + a);}}
在Program.cs文件添加如下代码:
class Program{ static void Main(string[] args){Overload overload = new Overload();overload.Display();Console.ReadKey();}}
运行结果如下:
Akhil 100
Mittal 100
OOP 100
Akhil 200
C#提供了params动态参数数组机制,非常方便的在运行时动态传递不同数量的同类型参数。
注:params关键词仅能作为函数的最后一个参数适用。
我们再试试params关键字的函数签名和非params关键字函数签名的优先级顺序:
public class Overload{ public void Display(){DisplayOverload(200);DisplayOverload(200, 300);DisplayOverload(200, 300, 500, 600);} private void DisplayOverload(int x, int y){Console.WriteLine("The two integers " + x + " " + y);} private void DisplayOverload(params int[] parameterArray){Console.WriteLine("parameterArray");}}
Program.cs文件添加如下代码:
class Program{ static void Main(string[] args){Overload overload = new Overload();overload.Display();Console.ReadKey();}}
运行结果如下:
parameterArray
The two integers 200 300
parameterArray
从运行结果看,C#非常巧妙的进行非params函数的精准匹配优先,如1个int类型\3个int类型,则用params类型匹配;2个int类型,用明确定义的函数进行匹配。
5 结论
在本节中,我们进行OOP系列的第一篇,主要说明了编译器的多态,它也称为早期绑定或者方法重载。同时,我们也学习C#中威力强大的params关键字,并用它来实现多态。
本文要点归纳如下:
C#函数重载的签名规则是用参数的类型和数量判断,而不是函数的名字。
函数返回值不作为重载签名。
修饰符不作为签名的一部分,如static
同函数中,多个参数名称要唯一
ref、out是引用传递,传递的是参数的内存地址
params 作为参数关键词,仅能用于函数的最后一个参数
深入浅出OOP(一): 多态和继承(早期绑定/编译时多态)相关推荐
- 编译时多态、运行时多态
根据何时确定执行多态方法中的哪一个,多态分为两种情况:编译时多态和运行时多态.如果在编译时能够确定执行多态方法 中的哪一个,称为编译时多态,否则称为运行时多态. 一.编译时多态 方法重载 ...
- C++编译时多态和运行时多态
C++编译时多态和运行时多态 作者:melonstreet 出处:https://www.cnblogs.com/QG-whz/p/5132745.html 本文版权归作者和博客园共有,欢迎转载,但未 ...
- java面向对象三大特性之多态---编译时多态和运行时多态详解
一.引言 1.什么是多态? 说到重载和重写,大家可能都知道.它们都是多态性的体现,那么说什么是多态呢?多态是指允许不同子类型的对象对同一行为作出不同的响应.例如在生活中,比如跑的动作,小猫.小狗和大象 ...
- c++多态之 运行时多态与编译时多态
多态的定义: 同一操作作用与不同的对象,可以有不同的解释,产生不同的执行结果. (1)编译时多态/静态联编 指联编工作在编译阶段完成,即在编译阶段确定了程序中的操作调用与执行该操作的代码间的关系,基于 ...
- 编译时多态和运行时多态
在JAVA中有两种多态是指:运行时多态和编译时多态. 关于类的多态性简介如下: 多态(polymorphism)意为一个名字可具有多种语义.在程序设计语言中,多态性是指"一种定义,多种实现& ...
- java编译时多态和运行时多态_运行时多态、编译时多态和重载、重写的关系(不区分Java和C#,保证能看懂!)...
以前在大学学习OOP的时候,知道了重载和重写的区别,但如果要把他们和多态联系起来,我想很多新手朋友和我当初一样是死记的,可是时间长了,自然而然就忘记了,最近在写测试的时候,终于"开窍&quo ...
- C语言的“编译时多态”
typeof 在 kernel 中的使用 -- C 语言的"编译时多态" C 语言本身没有多态的概念,函数没有重载的概念.然而随着 C 语言编写的软件逐渐庞大,越来越多地需要引入一 ...
- java多态编译,java多态 运行时多态和编译时多态
java多态 运行时多态和编译时多态 我们知道java的多态是一个重要的特性,其中体现java的多态有两种形式.运行时的多态和编译时的多态. 编译时的多态会发生在方法重载的时候,方法的重载指方法名相同 ...
- java多态编译_关于java:编译时多态是否是这样的运行时多态?
通过研究,我了解到: 重载,运算符重载和重载是我们所说的多态. 多态性意味着同一实体有时表现不同 例如: 参数 add(12, 13); add(12.2, 13.3); 相同实体(add())有时会 ...
最新文章
- MySQL在创建相同表结构时as和like 使用的区别
- Map、Set、List简介
- “猜画小歌”的一些细节和思考
- SSL,SSH,OpenSSL,OpenSSH,HTTPS的区别
- 极路由安全设计架构分析
- JS - 讨论 - 编码习惯 - JavaScript代码到底要不要写分号?
- UWP Acrylic Material
- 时隔一年,盘点CVPR 2019影响力最大的20篇论文
- 大规模分布式系统资源管理(二)
- android 访问本地image url_微信图片无法通过 WXSS 获取,可使用网络图片或 base64或image...
- 计算机金融sci,FINANCE AND STOCHASTICS《金融与随机分析》SSCI论文投稿_SSCI期刊大全_SSCI期刊点评_万维书刊网...
- win7原版镜像_封装二:Win7 预装软件 Setup 包集成方法
- 嵌入式工程师待遇北京地区最高
- “中国如果有五个丘成桐,数学肯定世界一流”
- 【通俗易懂】机器学习中 L1 和 L2 正则化的直观解释
- python中test是什么意思_Python unittest 之一: 什么是单元测试
- [转载]关于sql连接语句中的Integrated Security=SSPI
- H3C新版本模拟器HCL_Setup_V3.0.1安装流程
- matlab图注的上标和下标,关于matlab中特殊字符, 上标和下标
- 序列循环oracle,Oracle创建序列及循环自增取值问题-Oracle
热门文章
- Vim Vundle YouCompleteMe
- 【转】Dubbo架构设计详解
- CardLayout使用
- NPM流行包再起波澜:维护人员对俄罗斯用户发特定消息,谁来保证开源可信?...
- 开源的电信堆栈软件 FreeSwitch 中存在五个漏洞
- 很多大企业都在用的Pentaho 商业分析软件中存在多个严重缺陷
- VMware 修复 Fusion 和 Horizon 中的两个提权漏洞
- 战“疫”日记②|火神山小分队:像听到发令枪一样;徐碧江带勇士集结长沙“小汤山”...
- 天工软件在正射项目中的应用与常见问题解答
- 运维利器screen