封装,继承,多态

面向对象编程的三大特点,很基础的东西,开发中可以说时时刻刻都有用到,因此做个小小的总结。

一. 封装

我们写的方法,接口,都叫封装,就是把具体的属性和方法实现隐藏起来,只为特定的对象提供访问功能,调用者不必知道具体的内部逻辑。

就比如我们写一个方法 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,不同的派生类来实现具体方法。

posted @ 2019-07-27 17:00  luytest  阅读(214)  评论(0编辑  收藏  举报