面向对象编程的三大特点,很基础的东西,开发中可以说时时刻刻都有用到,因此做个小小的总结。
一. 封装
我们写的方法,接口,都叫封装,就是把具体的属性和方法实现隐藏起来,只为特定的对象提供访问功能,调用者不必知道具体的内部逻辑。
就比如我们写一个方法 public string retrunString(string str),调用者只需要知道方法名,已经定义的入参,返回值的类型就行了,对于内部如果操作入参的逻辑,不需要知道。
二. 继承
继承就是根据一个类来定义另一个类(这个过程叫派生)。原有的类成为基类/父类,派生出来的成为派生类/子类,它们的关系是 “is a”。
举例说,我们定义了一个类 动物 ,那么 猫,狗,猪都属于这个类的子类。
一个类可以派生自多个类或接口,这意味着它可以从多个基类或接口继承数据和函数。
实例:
using System;
namespace InheritanceApplication
{
class Shape
{
public void setWidth(int w)
{
width = w;
}
public void setHeight(int h)
{
height = h;
}
protected int width;
protected int height;
}
// 派生类
class Rectangle: Shape
{
public int getArea()
{
return (width * height);
}
}
class RectangleTester
{
static void Main(string[] args)
{
Rectangle Rect = new Rectangle();
Rect.setWidth(5);
Rect.setHeight(7);
Console.WriteLine("总面积: {0}", Rect.getArea());
Console.ReadKey();
}
}
}
这里可以看到,派生类Rectangle中并没有setWidth,setHeight方法,也没有定义width ,height属性,这些都是来自于基类Shape ,派生类调用了基类的2个赋值方法为width 和height两个属性赋值,然后再调用基类的getArea()方法输出结果。
结果是 总面积: 35
-------------------------------------------------------------------------------------------------------------------------------------
派生类继承了基类的成员变量和成员方法。因此父类对象应在子类对象创建之前被创建。
再来一个例子
class Rectangle
{
// 成员变量
protected double length;
protected double width;
public Rectangle(double l, double w)
{
length = l;
width = w;
}
public double GetArea()
{
return length * width;
}
public void Display()
{
Console.WriteLine("长度: {0}", length);
Console.WriteLine("宽度: {0}", width);
Console.WriteLine("面积: {0}", GetArea());
}
}
class Tabletop : Rectangle
{
private double cost;
public Tabletop(double l, double w) : base(l, w)
{ }
public double GetCost()
{
double cost;
cost = GetArea() * 70;
return cost;
}
public void Display()
{
base.Display();
Console.WriteLine("成本: {0}", GetCost());
}
}
class ExecuteRectangle
{
static void Main(string[] args)
{
Tabletop t = new Tabletop(4.5, 7.5);
t.Display();
Console.ReadLine();
}
}
基类中是通过有2个入参的构造函数 Rectangle(double l, double w) 为属性赋值,这与上例不同,上例是有2个赋值的方法,那么如果我们在派生类的构造函数public Tabletop(double l, double w) : base(l, w)中,没有: base(l, w)会怎样呢?答案是 输出的长宽面积成本都是0,因为如果不指定基类的构造函数时,会自动调用一个默认的,没有参数的构造函数,在此例中为Rectangle(),而我们为长宽赋值的操作是在Rectangle(double l, double w)中的,因此就没有为这两个属性赋值。具体会在构造函数文章中说明。
此例输出结果是 长度: 4.5
宽度: 7.5
面积: 33.75
成本: 2362.5
需要注意的是,c#不支持多重继承,可以由 动物派生狗,狗派生金毛,但是不能金毛同时继承狗和动物,即 class C : B,class B : A,这样C就可以继承了B和A中的属性和方法,但是不能 Class C : B,A。如果想多重继承,可以用接口。
三。 多态
多态是同一个行为具有多个不同表现形式或形态的能力。
多态性意味着有多重形式。在面向对象编程范式中,多态性往往表现为"一个接口,多个功能"。
多态性可以是静态的或动态的。在静态多态性中,函数的响应是在编译时发生的。在动态多态性中,函数的响应是在运行时发生的。
我们常用的方法重载,就是多态的体现,它属于静态多态。
动态多态性主要体现在 抽象类abstract,虚方法virtual,不同的派生类来实现具体方法。