在本系列中,我们以CodeProject上比较火的OOP系列博客为主,进行OOP深入浅出展现。

无论作为软件设计的高手、或者菜鸟,对于架构设计而言,均需要多次重构、取舍,以有利于整个软件项目的健康构建,有些经验是前辈总结的,我们拿来使用即可,有些是团队知识沉淀的,总之复用前人好的思想有利于减少返工。当然,在面试的时候,如果能围绕OOP大谈特谈,自然会加分多多的。

开始阅读本系列博客的预备知识,多态、封装、面向对象编程等,请通过MSDN学习。如下图的术语,您应该耳熟能详的。本系列文章使用C#作为唯一编程语言。

OOP

是什么OOP,以及OOP的优势是什么?

OOP代表的是面向对象编程(Object-Oriented Programming),它基于对象的整体进行编程,取代了基于过程函数的编程思想。具体实现是围绕对象进行数据、函数封装,而不是基于逻辑关系。OOP中的对象直达的是一个特定的类型、或者某类型的实例对象、更多时候是一个class。每个class对象的结构基本相似,但是有各自特有的属性和数据值。对象之间可通过对外的接口进行访问:方法、属性等。基于OOP的这些优势,独立的对象可以修改而不会影响到其他对象,这样会比较方便的升级软件减少潜在的bug。软件系统随着时间的推移,会变得越来越大,OOP编程思想有效的提高了系统代码的可读性和管理性。

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函数的调用、执行。

多态(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();
overload.DisplayOverload("method overloading");
overload.DisplayOverload("method overloading", );
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 = ;
} 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传递参数修饰符也不能作为重载签名。


多态中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(, "Akhil", "Mittal", "OOP");
DisplayOverload(, "Akhil");
DisplayOverload();
} 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();
DisplayOverload(, );
DisplayOverload(, , , );
} 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类型,用明确定义的函数进行匹配。

结论

在本节中,我们进行OOP系列的第一篇,主要说明了编译器的多态,它也称为早期绑定或者方法重载。同时,我们也学习C#中威力强大的params关键字,并用它来实现多态。

本文要点归纳如下:

  • C#函数重载的签名规则是用参数的类型和数量判断,而不是函数的名字。
  • 函数返回值不作为重载签名。
  • 修饰符不作为签名的一部分,如static
  • 同函数中,多个参数名称要唯一
  • ref、out是引用传递,传递的是参数的内存地址
  • params 作为参数关键词,仅能用于函数的最后一个参数

原文地址:http://www.codeproject.com/Articles/771455/Diving-in-OOP-Day-Polymorphism-and-Inheritance-Ear

译文地址:http://www.cnblogs.com/powertoolsteam/p/Diving-in-OOP-Day-Polymorphism-and-Inheritance-Ear.html

深入理解OOP(第一天):多态和继承(初期绑定和编译时多态)的更多相关文章

  1. c#中运行时编译时 多态

    c#中运行时编译时 多态   public class aa { } public class bb:aa { } public class cc { public static void Main( ...

  2. Java编译时多态和运行时多态

    来源:https://blog.csdn.net/wendizhou/article/details/73733061 编译时多态:主要是方法的重载,通过参数列表的不同来区分不同的方法. 运行时多态: ...

  3. 深入浅出OOP(一): 多态和继承(早期绑定/编译时多态)

    在本系列中,我们以CodeProject上比较火的OOP系列博客为主,进行OOP深入浅出展现. 无论作为软件设计的高手.或者菜鸟,对于架构设计而言,均需要多次重构.取舍,以有利于整个软件项目的健康构建 ...

  4. 深入理解OOP(三):多态和继承(动态绑定和运行时多态)

    在前面的文章中,我们介绍了编译期多态.params关键字.实例化.base关键字等.本节我们来关注另外一种多态:运行时多态, 运行时多态也叫迟绑定. 深入理解OOP(一):多态和继承(初期绑定和编译时 ...

  5. 深入理解OOP(四): 多态和继承(抽象类)

    在本文中,我们讨论OOP中的热点之一:抽象类.抽象类在各个编程语言中概念是一致的,但是C#稍微有些不一样.本文中我们会通过代码来实现抽象类,并一一进行解析. 深入理解OOP(一):多态和继承(初期绑定 ...

  6. 深入理解OOP(二):多态和继承(继承)

    本文是深入浅出OOP第二篇,主要说说继承的话题. 深入理解OOP(一):多态和继承(初期绑定和编译时多态) 深入理解OOP(二):多态和继承(继承) 深入理解OOP(三):多态和继承(动态绑定和运行时 ...

  7. C#面向对象(OOP)入门—第一天—多态和继承(方法重载)

    面向对象是什么 面向对象是一种基于对象的编程方法,它取代了仅仅依靠方法和流程的编程方式.面向对象的编程语言中,对象(object)其实就是指特定类型.或某个类的实例.面向对象使得编程人员更容易组织和管 ...

  8. 深入浅出OOP(三): 多态和继承(动态绑定/运行时多态)

    在前面的文章中,我们介绍了编译期多态.params关键字.实例化.base关键字等.本节我们来关注另外一种多态:运行时多态, 运行时多态也叫迟绑定. 运行时多态或迟绑定.动态绑定 在C#语音中,运行时 ...

  9. 深入理解Java面向对象三大特性 封装 继承 多态

    1.封装 封装的定义: 首先是抽象,把事物抽象成一个类,其次才是封装,将事物拥有的属性和动作隐藏起来,只保留特定的方法与外界联系 为什么需要封装: 封装符合面向对象设计原则的第一条:单一性原则,一个类 ...

随机推荐

  1. linux screen 命令详解[转]

    一.背景 系统管理员经常需要SSH 或者telent 远程登录到Linux 服务器,经常运行一些需要很长时间才能完成的任务,比如系统备份.ftp 传输等等.通常情况下我们都是为每一个这样的任务开一个远 ...

  2. A cost-effective recommender system for taxi drivers

    一个针对出租车司机有效花费的推荐系统 摘要 GPS技术和新形式的城市地理学改变了手机服务的形式.比如说,丰富的出租车GPS轨迹使得出做租车领域有新方法.事实上,最近很多工作是在使用出租车GPS轨迹数据 ...

  3. 烂泥:puppet添加带密码的用户

    本文由秀依林枫提供友情赞助,首发于烂泥行天下. 前一篇文章,我们介绍了有关puppet3.7的安装与配置,这篇文章我们再来介绍下如何利用puppet添加带密码的用户. 要通过puppet添加带密码的用 ...

  4. 烂泥:KVM、kickstart与nginx集成

    本文由秀依林枫提供友情赞助,首发于烂泥行天下. 前几篇文章介绍了FTP.NFS与KVM.kickstart集成的案例,从这篇文章开始,我们来介绍HTTP方式与KVM.kickstart集成. HTTP ...

  5. 使用DBI(perl)实现文本文件的导入导出mysql

    DBI 是perl脚本连接数据库的一个模块.perl脚本相对shell更灵活,功能更强大,跨平台能力强.相对可执行jar包要简单很多. ​1.下载安装包DBI-1.631.tar.gzperl脚本下载 ...

  6. spring 注入一个以枚举类型对象

    1.枚举 在实际编程中,往往存在着这样的“数据集”,它们的数值在程序中是稳定的,而且“数据集”中的元素是有限的. 例如星期一到星期日七个数据元素组成了一周的“数据集”,春夏秋冬四个数据元素组成了四季的 ...

  7. js实现打开网页自动弹出添加QQ好友邀请窗口

    我们有时进一些网面或专题页面会自动弹出一个加为好友的对话框了,在研究了很久之后发现可以直接使用js来实现,下面我们一起来看js实现打开网页自动弹出添加QQ好友邀请窗口的方法. 第一步.JS脚本 这个是 ...

  8. 《超级IP》:伪理论,没能比现有的市场营销理论更高明,只敢勉强去解释已经发生的事情,不敢去预测未来。2星。

    超级IP是作者造出来的一个词.作者尝试把“超级IP”作为一种理论来解释2015年以来的各种网红现象.读完全书后,我的感觉是这个理论不怎么样: 1:作者完全不提现有的市场营销理论.我的问题是:现有的理论 ...

  9. Java 三大特性——封装、继承、多态

    一.封装 封装,实际就是把属于同一类事物的共性(包括属性与方法)归到一个类中,以方便使用. 概念:在面向对象程式设计方法中,封装(英语:Encapsulation)是指,一种将抽象性函式接口的实作细节 ...

  10. 《Writing Idiomatic Python》前两部分的中文翻译

    汇总了一下这本小书前两部分的内容: 翻译<Writing Idiomatic Python>(一):if语句.for循环 翻译<Writing Idiomatic Python> ...