c# 面相对象4-多态性
一、定义:
多态是面向对象程序设计的又一个特性。在面向过程的程序设计中,主要工作是编写一个个的过程或函数,这些过程和函数不能重名。例如在一个应用中,需要对数值型数据进行排序,还需要对字符型数据进行排序,虽然使用的排序方法相同,但要定义两个不同的过程(过程的名称也不同)来实现。
在面向对象程序设计中,可以利用“重名”来提高程序的抽象度和简洁性。首先我们来理解实际的现象,例如,“启动”是所有交通工具都具有的操作,但是不同的具体交通工具,其“启动”操作的具体实现是不同的,如汽车的启动是“发动机点火——启动引擎”、“启动”轮船时要“起锚”、气球飞艇的“启动”是“充气——解缆”。如果不允许这些功能使用相同的名字,就必须分别定义“汽车启动”、“轮船启动”、“气球飞艇启动”多个方法。这样一来,用户在使用时需要记忆很多名字,继承的优势就荡然无存了。为了解决这个问题,在面向对象的程序设计中引入了多态的机制。
多态是指一个程序中同名的不同方法共存的情况。主要通过子类对父类方法的覆盖来实现多态。这样一来,不同类的对象可以响应同名的方法来完成特定的功能,但其具体的实现方法却可以不同。例如同样的加法,把两个时间加在一起和把两个整数加在一起肯定完全不同。
通过方法覆盖,子类可以重新实现父类的某些方法,使其具有自己的特征。例如对于车类的加速方法,其子类(如赛车)中可能增加了一些新的部件来改善提高加速性能,这时可以在赛车类中覆盖父类的加速方法。覆盖隐藏了父类的方法,使子类拥有自己的具体实现,更进一步表明了与父类相比,子类所具有的特殊性。
多态性使语言具有灵活、抽象、行为共享的优势,很好地解决了应用程序函数同名问题。
二、实现的方法
多态需要通过继承来实现。
三、分类
1、编译多态(重载overload)
eg、 函数重载
重载(overload):在同一个作用域(一般指一个类)的两个或多个方法函数名相同,参数列表不同的方法叫做重载,它们有三个特点(俗称两必须一可以):
- 方法名必须相同
- 参数列表必须不相同
- 返回值类型可以不相同
如:
public void Sleep()
{
Console.WriteLine("Animal睡觉");
}
public int Sleep(int time)
{
Console.WriteLine("Animal{0}点睡觉", time);
return time;
}
2、运行多态(重写override)
- 相同的方法名
- 相同的参数列表
- 相同的返回值。
如:父类中的定义:
public virtual void EatFood()
{
Console.WriteLine("Animal吃东西");
} 子类中的定义: public override void EatFood()
{
Console.WriteLine("Cat吃东西");
//base.EatFood();
}实现方式:
父类引用指向子类
例子:namespace mydemo1
{
class Ren
{
public virtual void Speak()//
{
}
} class Ghost
{
public void Eat(Ren e)
{
e.Speak();
Console.WriteLine("人类真好吃!");
}
} class China : Ren
{
public override void Speak()
{
Console.WriteLine("汉语");
}
} class Usa : Ren
{
public override void Speak()
{
Console.WriteLine("English");
}
} class Program
{
public static void Main(string[] args)
{
Ren a = new China();//父类的引用指向子类的实例
Ren b = new Usa(); //a.Speak();
//b.Speak(); Ghost g = new Ghost();
China c = new China();
Usa u = new Usa(); Random r = new Random();
int a = r.Next(, ); if (a == )
{
g.Eat(c);//改eat()方法传入的参数要求是Ren类的引用,可以向里面传其子类及父类的元素,子类对象代替父类对象
}
else
{
g.Eat(u);
} }
}
}3、虚方法
:即为基类中定义的允许在派生类中重写的方法,使用virtual关键字定义。
如:
public virtual void EatFood()
{
Console.WriteLine("Animal吃东西");
}注意虚方法也可以直接调用
Animal a = new Animal();
a.EatFood();运行结果:
- 4、抽象方法:在基类中定义的并且必须在派生类中重写的方法,使用abstract关键字定义。如:
public abstract class Biology
{
public abstract void Live();
}
public class Animal : Biology
{
public override void Live()
{
Console.WriteLine("Animal重写的抽象方法");
//throw new NotImplementedException();
}
}注意:抽象方法只能在抽象类中定义,如果不在抽象类中定义,则会报出如下错误:
5、里氏代换原则和抽象依赖原则
里氏代换原则
如果某个方法接收的是父类引用,可以向里面传父类或其子类的元素,子类对象替代父类对象
例子:怪兽吃人
class Guaishou
{
public void Eat(Ren r)
{
r.Jiao();
Console.WriteLine("人类真好吃");
}
} class Ren
{
public virtual void Speak()
{
Console.WriteLine("说话");
} public virtual void Jiao()
{
Console.WriteLine("");
} } class American:Ren
{
public override void Speak()
{
Console.WriteLine("Hello");
} public override void Jiao()
{
Console.WriteLine("SOS");
}
} class Chinese:Ren
{
public override void Speak()
{
Console.WriteLine("你好");
}
public override void Jiao()
{
Console.WriteLine("救命");
} } class Program
{
static void Main(string[] args)
{
//Ren a = new Chinese();
//a.Speak();
//a = new American();
//a.Speak(); Guaishou g = new Guaishou(); //Ren ren; Random r = new Random();
int a = r.Next(,); if(a==)
{
American ren= new American();
g.Eat(ren);
}
else
{
Chinese ren = new Chinese();
g.Eat(ren);
} }
}
}
抽象依赖原则
用父类的引用来指向子类的实例
例子:运行多态的例子
6、隐藏方法:在派生类中定义的和基类中的某个方法同名的方法,使用new关键字定义。
如在基类Animal中有一方法Sleep():
public void Sleep()
{
Console.WriteLine("Animal Sleep");
}
则在派生类Cat中定义隐藏方法的代码为:
new public void Sleep()
{
Console.WriteLine("Cat Sleep");
}
或者为:
public new void Sleep()
{
Console.WriteLine("Cat Sleep");
}
注意:(1)隐藏方法不但可以隐藏基类中的虚方法,而且也可以隐藏基类中的非虚方法。
public abstract class Biology
{
public abstract void Live();
}
public class Animal : Biology
{
public override void Live()
{
Console.WriteLine("Animal重写的Live");
//throw new NotImplementedException();
}
public void Sleep()
{
Console.WriteLine("Animal Sleep");
}
public int Sleep(int time)
{
Console.WriteLine("Animal在{0}点Sleep", time);
return time;
}
public virtual void EatFood()
{
Console.WriteLine("Animal EatFood");
}
}
public class Cat : Animal
{
public override void EatFood()
{
Console.WriteLine("Cat EatFood");
//base.EatFood();
}
new public void Sleep()
{
Console.WriteLine("Cat Sleep");
}
//public new void Sleep()
//{
// Console.WriteLine("Cat Sleep");
//}
}
public class Dog : Animal
{
public override void EatFood()
{
Console.WriteLine("Dog EatFood");
//base.EatFood();
}
}
需要执行的代码:
class Program
{
static void Main(string[] args)
{
//Animal的实例
Animal a = new Animal();
//Animal的实例,引用派生类Cat对象
Animal ac = new Cat();
//Animal的实例,引用派生类Dog对象
Animal ad = new Dog();
//Cat的实例
Cat c = new Cat();
//Dog的实例
Dog d = new Dog();
//重载
a.Sleep();
a.Sleep();
//重写和虚方法
a.EatFood();
ac.EatFood();
ad.EatFood();
//抽象方法
a.Live();
//隐藏方法
a.Sleep();
ac.Sleep();
c.Sleep();
Console.ReadKey();
}
}
c# 面相对象4-多态性的更多相关文章
- Java对象的多态性(转型)
多态性在面向对象中主要有两种体现: <1>方法的重载与覆写 <2>对象的多态性 对象的多态性:向上转型:子类对象-->父类对象,向上转型会自动完成 向下转型:父类对象-- ...
- js编程-面相对象
//js面相对象编程 //定义constructor构造方法 function myFn(name,sex){ this.name = name; this.sex = sex; } //用proto ...
- 文成小盆友python-num7 -常用模块补充 ,python 牛逼的面相对象
本篇内容: 常用模块的补充 python面相对象 一.常用模块补充 1.configparser模块 configparser 用于处理特定格式的文件,起内部是调用open()来实现的,他的使用场景是 ...
- java上转型和下转型(对象的多态性)
/*上转型和下转型(对象的多态性) *上转型:是子类对象由父类引用,格式:parent p=new son *也就是说,想要上转型的前提必须是有继承关系的两个类. *在调用方法的时候,上转型对象只能调 ...
- Java开发知识之Java面相对象
Java开发知识之Java面相对象上 一丶什么是面相对象 了解什么什么是面相对象.那么首先要了解什么是面相过程. 面相过程的意思就是. 什么事情都亲力亲为. 比如上一讲的排序算法. 我们自己写的. 这 ...
- python 的面相对象编程--对应c++
在python的面相对象编程中,我们常常在class中可以看到a(), _b() , __c(), __d()__这样的函数. 由于我是看廖雪峰老师的教程,廖老师为了简单起见,没有引入太多概念,我 ...
- Java面向对象-对象的多态性
Java面向对象-对象的多态性 Java中的多态性表现: 1,方法的重载和重写(覆盖): 2,可以用父类的引用指向子类的具体实现,而且可以随时更换为其他子类的具体实现: 我们先搞个父类Animal: ...
- 201871010101-陈来弟《面相对象程序设计(java)》第十周学习总结
201871010101-陈来弟<面相对象程序设计(java)>第十周学习总结 实验八异常.断言与日志 实验时间 2019-11-1 1.实验目的与要求 (1) 掌握java异常处理技术: ...
- 初识python:tkinter 实现 弹球小游戏(非面相对象)
通过 tkinter 采用非面相对象式实现弹球小游戏(使用蹩脚式面相对象实现). #!/user/bin env python # author:Simple-Sir # time:2020/8/3 ...
- c# 面相对象3-之继承性
继承:类与类之间的关系(父子关系) 子类继承父类,那么子类就拥有父类的公共属性和方法一个子类只能继承一个父类,一个父类可以有好多子类子类对象可以直接转成父类,但父类只能转回对应的子类如果子类转成父类之 ...
随机推荐
- CLR via C# - Char_String - Format
//前面那个本来想重新编辑的,但是那个编辑器之前被我调到Markdown之后,改回Tiny MCE编辑器不出来 1.ToString()方法 & IFormattable & IFor ...
- json返回数据拼接HTML
<div class="box-lists"> </div> $.ajax({ url: 'AjaxPage/AjaxHandler.ashx', typ ...
- ajax参数中出现空格
jquery中发起ajax请求时的参数名中不能有空格.如果是get请求参数的中的空格会变成“+”符而在post请求中看不到这种变化,但无论哪种情况都无法与服务接口的参数就行匹配(此时进行调试也不会触发 ...
- Android——ExpandableListView事件拦截
1.满足条件 如果使用ExpandableListView,需要子item响应一个事件,比如重新启动一个新的activity,需要满足下面的条件: (1).修改Adapter返回值 覆写BaseExp ...
- 解决iOS9苹果将原http协议改成了https协议问题
解决方法: 在info.plist 加入key <key>NSAppTransportSecurity</key> <dict> <key>NSAllo ...
- poj1458 求最长公共子序列 经典DP
Common Subsequence Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 45763 Accepted: 18 ...
- (转) class II
Overloading operators Classes, essentially, define new types to be used in C++ code. And types in ...
- Java中的IO学习总结
今天刚刚看完java的io流操作,把主要的脉络看了一遍,不能保证以后使用时都能得心应手,但是最起码用到时知道有这么一个功能可以实现,下面对学习进行一下简单的总结: IO流主要用于硬盘.内存.键盘等处理 ...
- spring 上传图片
@RequestMapping(value = "/upload",method = RequestMethod.POST) public String upload(@Reque ...
- Lucene学习总结之三:Lucene的索引文件格式(1)
Lucene的索引里面存了些什么,如何存放的,也即Lucene的索引文件格式,是读懂Lucene源代码的一把钥匙. 当我们真正进入到Lucene源代码之中的时候,我们会发现: Lucene的索引过程, ...