回想一下,虽然代码会敲,但是从文字方面还真的不太理解面向对象,故搜集加整理一下,以巩固记忆。
引用一篇大佬的分析,很透彻。。。:C#面向对象简单理解
什么是面向对象
面向对象(Object-oriented Programming)编程也叫做OOP编程,是结构化编程,对程序中的变量结构划分,让编程更清晰。
面向对象三大特性
封装(encapsulation)
把一个或多个项目封闭在一个物理的或者逻辑的包中。类可以将它的成员私有化,只暴露它认为应当暴露给外界的成员。通过私有化成员,外界不必了解这些成员的实现细节。通过给类及类中的成员变量、属性和方法设置不同的访问修饰符(public、protected、internal、protected internal、private)来控制它们的作用范围,以达到封装的目的。
各访问修饰符作用范围如下:
访问修饰符 | 说明 |
public | 公有访问,不受任何限制。 |
protected | 保护访问,只限于本类内部和子类内部可以访问,实例不能访问。 |
internal | 内部访问,只限于本项目内访问,其他不能访问。 |
protected internal | 内部保护访问,只限于本项目和子类访问,其他不能访问。(protected 和internal 的权限之和) |
private | 私有访问,只限于本类成员内访问,子类、实例都不能访问 |
封装的好处:
- 良好的封装,能够减少耦合
- 类的内部的实现可以自由的修改
- 类具有清晰的对外接口
实例:
namespace Encapsulation
{
public delegate void SayEventHandler();
public class Class1 {}
public struct Range
{
public int Start;
public int End;
}
public abstract class AbsClass {}
public enum Gender
{
男,
女,
}
}
程序调用如图:
继承(inheritance)
子类可以继承父类,从而简单的自动实现父类所有的成员,并增加自己的成员,有自己的特性。通过方法的重写和隐藏,子类还可以修改父类的行为。继承是面向对象程序设计代码服用能力的一种体现。
如果子类继承父类:
- 子类拥有父类非private的属性和功能
- 子类具有自己的属性和功能,即子类可以扩展父类没有的属性和功能
- 子类还可以以自己的方式实现父类的功能(方法重写)
实例:
namespace inheritance
{
class baseClass1
{
public string str="baseclass1";
}
class baseClass2
{
public string str="baseclass2";
}
class inheritClass:baseClass1
{
public string language="C#";
}
class Program
{
static void Main(string[] args)
{
Console.WriteLine("----------------程序开始-----------")
inheritClass inheritclass=new inheritClass();
Console.WriteLine(inheritclass.str);
Console.WriteLine(inheritclass.language);
Console.WriteLine("----------------程序结束-----------")
Console.ReadKey();
}
}
}
程序的输出结果为:
----------------程序开始-----------
baseclass1
C#
----------------程序结束-----------
多态(polymorphism)
是继承的一种特殊情况,此时,子类一定会复写父类的行为(通常父类没有提供代码)。对于相同的方法,不同类型的子类有着不同的实现。接口和抽象类都是多态的体现。多态的原理是当方法被调用时,无论对象是否被转换为其父类,都只有位于对象继承链最末端的方法实现会被调用,也就是说,虚方法是按照其运行时类型,而非编译时类型进行动态绑定调用的。
例1:
public class Animal
{
public virtual void Eat()
{
Console.WriteLine("Animal eat");
}
}
public class Cat : Animal
{
public override void Eat()
{
Console.WriteLine("Cat eat");
}
}
public class Dog : Animal
{
public override void Eat()
{
Console.WriteLine("Dog eat");
}
}
class Tester
{
static void Main(string[] args)
{
Animal[] animals = new Animal[3];
animals[0] = new Animal();
animals[1] = new Cat();
animals[2] = new Dog();
for (int i = 0; i < 3; i++)
{
animals[i].Eat();
}
}
}
例2: new的用法
public class Animal
{
public virtual void Eat()
{
Console.WriteLine("Animal eat");
}
}
public class Cat : Animal
{
public new void Eat()
{
Console.WriteLine("Cat eat");
}
}
class Tester
{
static void Main(string[] args)
{
Animal a = new Animal();
a.Eat();
Animal ac = new Cat();
ac.Eat();
Cat c = new Cat();
c.Eat();
}
}
例3:override实现多态
public class Animal
{
public virtual void Eat()
{
Console.WriteLine("Animal eat");
}
}
public class Dog : Animal
{
public override void Eat()
{
Console.WriteLine("Dog eat");
}
}
public class WolfDog : Dog
{
public override void Eat()
{
Console.WriteLine("WolfDog eat");
}
}
class Tester
{
static void Main(string[] args)
{
Animal[] animals = new Animal[3];
animals[0] = new Animal();
animals[1] = new Dog();
animals[2] = new WolfDog();
for (int i = 0; i < 3; i++)
{
animals[i].Eat();
}
}
}
例4:abstract-override实现多态
public abstract class Animal
{
public abstract void Eat();
}
public class Cat : Animal
{
public override void Eat()
{
Console.WriteLine("Cat eat");
}
}
public class Dog : Animal
{
public override void Eat()
{
Console.WriteLine("Dog eat");
}
}
public class WolfDog : Dog
{
public override void Eat()
{
Console.WriteLine("Wolfdog eat");
}
}
class Tester
{
static void Main(string[] args)
{
Animal[] animals = new Animal[3];
animals[0] = new Cat();
animals[1] = new Dog();
animals[2] = new WolfDog();
for (int i = 0; i < animals.Length; i++)
{
animals[i].Eat();
}
}
}
以上程序的输出都为:
Cat eat
Dog eat
Wolfdog eat
面向对象的设计原则
- 单一职责原则(The Single Responsiblity Principle):一个类,最好只做一件事,只有一个引起它的变化。
- 开发-封闭原则(The Open - Close Principle):对于扩展是开放的,对于更改是封闭的
- Liskov替换原则(The Liskov Substitution Principle):子类必须能够替换其基类
- 依赖倒置原则(The Dependency Inversion Principle):依赖于抽象
- 接口隔离原则(The Interface Segregation Principle):使用多个小的专门的接口,而不要使用一个大的总接口