【学习笔记】面向对象三大特性封装、继承和多态
一、封装
1、隔离,外部不用关心怎么实现,只要接口不变,内部可以随意扩展。
2、数据安全 private protected 数据结构,只能通过公开方法来访问,而不是随便改。
3、降低耦合 提高重用性 尽量隐藏更多的东西。
二、继承
1、子类拥有父类的一切属性和行为,代码重用。
2、单继承,也就是只有一个父类。
三、多态
1、一个类可以用做多个类型,就是多态,当然还有方法。
2、编译时多态、运行时多态、接口多态、继承多态。
接下来我们来看个Demo,首先我们准备一些测试类
using System;
namespace MyOO
{
/// <summary>
/// 面向对象测试类
/// </summary>
public class OOTest : IFlyable, ISwimable
{
/// <summary>
/// 实现IFlyable接口
/// </summary>
public void Fly()
{
Console.WriteLine("OOTest Fly");
}
/// <summary>
/// 显示实现ISwimable接口,用于解决方法的重名问题
/// </summary>
void ISwimable.Swin()
{
Console.WriteLine("OOTest Swin");
}
/// <summary>
/// OOTest自己的Swin方法
/// </summary>
public void Swin()
{
Console.WriteLine("我是OOTest自己的Swin方法");
}
}
/// <summary>
/// 飞接口
/// </summary>
public interface IFlyable
{
/// <summary>
/// 飞
/// </summary>
void Fly();
}
/// <summary>
/// 游泳接口
/// </summary>
public interface ISwimable
{
/// <summary>
/// 游泳
/// </summary>
void Swin();
}
/// <summary>
/// 父类(抽象类)
/// </summary>
public abstract class ParentClass
{
/// <summary>
/// 构造函数
/// </summary>
public ParentClass(int id)
{
}
/// <summary>
/// 普通方法
/// </summary>
public void CommonMethod()
{
Console.WriteLine("ParentClass CommonMethod");
}
/// <summary>
/// virtual 虚方法 必须包含实现 但是可以被重载
/// </summary>
public virtual void VirtualMethod()
{
Console.WriteLine("ParentClass VirtualMethod");
}
/// <summary>
/// 虚方法重载
/// </summary>
/// <param name="name"></param>
public virtual void VirtualMethod(string name)
{
Console.WriteLine("ParentClass VirtualMethod");
}
/// <summary>
/// 抽象方法(必须放在抽象类中)
/// </summary>
public abstract void AbstractMethod();
}
/// <summary>
/// 子类
/// </summary>
public class ChildClass : ParentClass
{
/// <summary>
/// 实例化子类的时候,是先完成父类的实例化的
/// </summary>
public ChildClass()
: base(1)//调用父类的构造函数
{
}
/// <summary>
/// new 隐藏
/// </summary>
public new void CommonMethod()
{
Console.WriteLine("ChildClass CommonMethod");
}
/// <summary>
/// 普通方法重载一
/// </summary>
/// <param name="name"></param>
public void CommonMethod(string name)
{
Console.WriteLine("ChildClass CommonMethod OverLoad1");
}
/// <summary>
/// 普通方法重载二
/// </summary>
public void CommonMethod(string name, int id)
{
Console.WriteLine("ChildClass CommonMethod OverLoad2");
}
/// <summary>
/// virtual 可以被覆写
/// </summary>
/// <param name="obj"></param>
/// <returns></returns>
public override void VirtualMethod()
{
Console.WriteLine("ChildClass VirtualMethod");
base.VirtualMethod();//base表示调用直接父类的这个方法
}
/// <summary>
/// 抽象方法必须覆写(标记为sealed密封方法则不允许子类再去重写它)
/// </summary>
public sealed override void AbstractMethod()
{
Console.WriteLine("ChildClass AbstractMethod");
}
}
/// <summary>
/// 派生类
/// </summary>
public class GrandClass : ChildClass
{
//这是错误的,密封的,无法进行重写
//public override void AbstractMethod()
//{
// base.AbstractMethod();
//}
/// <summary>
/// 重写虚方法
/// </summary>
public override void VirtualMethod()
{
base.VirtualMethod();
}
}
}
然后来看下具体使用
using System;
namespace MyOO
{
/// <summary>
/// 小结:
/// 使用父类声明接收子类对象
/// 实现多态的几种方式:方法的隐藏、方法的重载、虚方法、抽象方法、接口
/// 1、方法的隐藏
/// 使用new关键字,这是个普通方法,普通方法调用是由编译时决定,调用的是父类的方法还是子类的方法取决于它的声明类型
///
/// 2、方法的重载
/// 这是编译时多态,方法的调用是由编译时决定的
///
/// 3、虚方法
/// 用virtual关键字,子类可以用override去重写它,这是运行时多态,如果子类有去实现父类的虚方法则调用子类的方法,否则调用父类的方法
///
/// 4、抽象方法
/// 用abstract关键字,子类需要用override关键字去覆写它,这是运行时多态,调用子类的方法
/// 含有抽象方法的类一定是抽象类,抽象类不能被实例化,抽象类中可以有抽象成员也可以有非抽象成员
///
/// 4、接口
/// 用interface关键字,子类去实现接口成员不需要用override关键字,这是运行时多态,调用子类的方法
/// 接口不能被实例化,接口成员不允许添加访问修饰符,默认是public
/// 接口成员必须是函数成员(本质都是方法),并且都是抽象成员不能有任何的实现,不能有常量和字段
/// 接口成员包括方法、属性、索引器、事件,不能有字段和构造函数
/// 接口可以继承多个接口
/// 显示实现接口的目的是为了解决方法的重名问题
/// </summary>
class Program
{
static void Main(string[] args)
{
//使用父类声明接收子类对象
ParentClass parent = new ChildClass();
//方法的隐藏
Console.WriteLine("下面是parent.CommonMethod()");
parent.CommonMethod();//子类new隐藏 父类方法 普通方法由编译时决定--提高效率
Console.WriteLine(); //换行
//虚方法
Console.WriteLine("下面是parent.VirtualMethod()");
parent.VirtualMethod();//子类覆写的虚方法 子类方法 虚方法由运行时决定的--多态灵活
Console.WriteLine(); //换行
//抽象方法
Console.WriteLine("下面是parent.AbstractMethod()");
parent.AbstractMethod();//子类实现的抽象方法 子类方法 抽象方法由运行时决定的--多态灵活
Console.WriteLine(); //换行
//接口
Console.WriteLine("下面是fly.Fly()");
IFlyable fly = new OOTest();
fly.Fly();//子类实现的抽象方法 子类方法 抽象方法由运行时决定的--多态灵活
Console.WriteLine(); //换行
Console.WriteLine("下面是swim.Swin()");
ISwimable swim = new OOTest();
swim.Swin();//子类实现的抽象方法 子类方法 抽象方法由运行时决定的--多态灵活
Console.WriteLine(); //换行
Console.WriteLine("下面是test.Swin()");
OOTest test = new OOTest();
test.Swin();//OOTest自己的Swin方法
Console.ReadKey();
}
}
}
最后我们来总结下多态的情况:
1、编译时多态:方法的重载,这个就不必多说了。
2、运行时多态:虚方法、抽象类、接口
1)什么时候用虚方法来实现多态?
可以抽象出一个父类,并且父类中可以写出这几个子类共有的方法,且知道具体实现方式,且还需要创建父类对象。
2)什么时候用抽象类来实现多态?
可以抽象出一个父类,并且父类中可以写出这几个子类共有的方法,但又不知道如何具体实现这些方法。
3)什么时候用接口来实现多态?
在几个类中根本找不出父类,但它们具有共同的行为、共同的能力。
Demo源码:
链接:https://pan.baidu.com/s/1-PWuGw5Yw3D_bSWuCDk26w
提取码:z9gh