C# 最基礎知識介紹–多態

前言:👻🎄

學過編程的人都知道有個名詞叫” O O P 思 想 ” —— {“面向對象編程“} ” 面 向 對 象 編 程 ” (Object Oriented Programming,OOP,面向對象程序設計)是一種計算機編程架構。OOP 的一條基本原則是計算機程序是由單個能夠起到子程序作用的單元或對象組合而成。OOP 達到瞭軟件工程的三個主要目標:重用性、靈活性和擴展性。為瞭實現整體運算,每個對象都能夠接收信息、處理數據和向其它對象發送信息 核心思想:封裝繼承多態.

一、C# 多態性

多態是同一個行為具有多個不同表現形式或形態的能力。

多態性意味著有多重形式。在面向對象編程范式中,多態性往往表現為”一個接口,多個功能”。 多態性可以是靜態的或動態的。在 靜態多態性 中,函數的響應是在編譯時發生的。在 動態多態性 中,函數的響應是在運行時發生的。 在 C# 中,每個類型都是多態的,因為包括用戶定義類型在內的所有類型都繼承自 Object。 多態就是同一個接口,使用不同的實例而執行不同操作,如圖所示:

現實中,比如我們按下 F1 鍵這個動作:

  • 如果當前在 Flash 界面下彈出的就是 AS 3 的幫助文檔;
  • 如果當前在 Word 下彈出的就是 Word 幫助;
  • 在 Windows 下彈出的就是 Windows 幫助和支持。
  • 同一個事件發生在不同的對象上會產生不同的結果。

二、靜態多態性

在編譯時,函數和對象的連接機制被稱為早期綁定,也被稱為靜態綁定。C# 提供瞭兩種技術來實現靜態多態性。分別為:

  • 函數重載
  • 運算符重載

三、函數重載

可以在同一個范圍內對相同的函數名有多個定義。函數的定義必須彼此不同,可以是參數列表中的參數類型不同,也可以是參數個數不同。不能重載隻有返回類型不同的函數聲明。

下面的實例演示瞭幾個相同的函數 Add() ,用於對不同個數參數進行相加處理:

實例:

using System;
namespace PolymorphismApplication
{
    public class TestData  
    {  
        public int Add(int a, int b, int c)  
        {  
            return a + b + c;  
        }  
        public int Add(int a, int b)  
        {  
            return a + b;  
        }  
    }  
    class Program  
    {  
        static void Main(string[] args)  
        {  
            TestData dataClass = new TestData();
            int add1 = dataClass.Add(1, 2);  
            int add2 = dataClass.Add(1, 2, 3);

            Console.WriteLine("add1 :" + add1);
            Console.WriteLine("add2 :" + add2);  
        }  
    }  
}

下面的實例演示瞭幾個相同的函數 print(),用於打印不同的數據類型:

實例:

using System;
namespace PolymorphismApplication
{
   class Printdata
   {
      void print(int i)
      {
         Console.WriteLine("輸出整型: {0}", i );
      }

      void print(double f)
      {
         Console.WriteLine("輸出浮點型: {0}" , f);
      }

      void print(string s)
      {
         Console.WriteLine("輸出字符串: {0}", s);
      }
      static void Main(string[] args)
      {
         Printdata p = new Printdata();
         // 調用 print 來打印整數
         p.print(1);
         // 調用 print 來打印浮點數
         p.print(1.23);
         // 調用 print 來打印字符串
         p.print("Hello Runoob");
         Console.ReadKey();
      }
   }
}

當上面的代碼被編譯和執行時,它會產生下列結果:

輸出整型: 1 輸出浮點型: 1.23 輸出字符串: Hello Runoob

四、C# 運算符重載

您可以重定義或重載 C# 中內置的運算符。因此,程序員也可以使用用戶自定義類型的運算符。重載運算符是具有特殊名稱的函數,是通過關鍵字 operator 後跟運算符的符號來定義的。與其他函數一樣,重載運算符有返回類型和參數列表。

例如,請看下面的函數:

public static Box operator+ (Box b, Box c)
{
   Box box = new Box();
   box.length = b.length + c.length;
   box.breadth = b.breadth + c.breadth;
   box.height = b.height + c.height;
   return box;
}

上面的函數為用戶自定義的類 Box 實現瞭加法運算符(+)。它把兩個 Box 對象的屬性相加,並返回相加後的 Box 對象。

1、運算符重載的實現

下面的程序演示瞭完整的實現:

實例:

using System;

namespace OperatorOvlApplication
{
   class Box
   {
      private double length;      // 長度
      private double breadth;     // 寬度
      private double height;      // 高度

      public double getVolume()
      {
         return length * breadth * height;
      }
      public void setLength( double len )
      {
         length = len;
      }

      public void setBreadth( double bre )
      {
         breadth = bre;
      }

      public void setHeight( double hei )
      {
         height = hei;
      }
      // 重載 + 運算符來把兩個 Box 對象相加
      public static Box operator+ (Box b, Box c)
      {
         Box box = new Box();
         box.length = b.length + c.length;
         box.breadth = b.breadth + c.breadth;
         box.height = b.height + c.height;
         return box;
      }

   }

   class Tester
   {
      static void Main(string[] args)
      {
         Box Box1 = new Box();         // 聲明 Box1,類型為 Box
         Box Box2 = new Box();         // 聲明 Box2,類型為 Box
         Box Box3 = new Box();         // 聲明 Box3,類型為 Box
         double volume = 0.0;          // 體積

         // Box1 詳述
         Box1.setLength(6.0);
         Box1.setBreadth(7.0);
         Box1.setHeight(5.0);

         // Box2 詳述
         Box2.setLength(12.0);
         Box2.setBreadth(13.0);
         Box2.setHeight(10.0);

         // Box1 的體積
         volume = Box1.getVolume();
         Console.WriteLine("Box1 的體積: {0}", volume);

         // Box2 的體積
         volume = Box2.getVolume();
         Console.WriteLine("Box2 的體積: {0}", volume);

         // 把兩個對象相加
         Box3 = Box1 + Box2;

         // Box3 的體積
         volume = Box3.getVolume();
         Console.WriteLine("Box3 的體積: {0}", volume);
         Console.ReadKey();
      }
   }
}

當上面的代碼被編譯和執行時,它會產生下列結果:

Box1 的體積: 210 Box2 的體積: 1560 Box3 的體積: 5400

2、可重載和不可重載運算符

下表描述瞭 C# 中運算符重載的能力:

實例針對上述討論,讓我們擴展上面的實例,重載更多的運算符:

實例:

using System;

namespace OperatorOvlApplication
{
    class Box
    {
       private double length;      // 長度
       private double breadth;     // 寬度
       private double height;      // 高度
     
       public double getVolume()
       {
         return length * breadth * height;
       }
      public void setLength( double len )
      {
          length = len;
      }

      public void setBreadth( double bre )
      {
          breadth = bre;
      }

      public void setHeight( double hei )
      {
          height = hei;
      }
      // 重載 + 運算符來把兩個 Box 對象相加
      public static Box operator+ (Box b, Box c)
      {
          Box box = new Box();
          box.length = b.length + c.length;
          box.breadth = b.breadth + c.breadth;
          box.height = b.height + c.height;
          return box;
      }
     
      public static bool operator == (Box lhs, Box rhs)
      {
          bool status = false;
          if (lhs.length == rhs.length && lhs.height == rhs.height
             && lhs.breadth == rhs.breadth)
          {
              status = true;
          }
          return status;
      }
      public static bool operator !=(Box lhs, Box rhs)
      {
          bool status = false;
          if (lhs.length != rhs.length || lhs.height != rhs.height
              || lhs.breadth != rhs.breadth)
          {
              status = true;
          }
          return status;
      }
      public static bool operator <(Box lhs, Box rhs)
      {
          bool status = false;
          if (lhs.length < rhs.length && lhs.height
              < rhs.height && lhs.breadth < rhs.breadth)
          {
              status = true;
          }
          return status;
      }

      public static bool operator >(Box lhs, Box rhs)
      {
          bool status = false;
          if (lhs.length > rhs.length && lhs.height
              > rhs.height && lhs.breadth > rhs.breadth)
          {
              status = true;
          }
          return status;
      }

      public static bool operator <=(Box lhs, Box rhs)
      {
          bool status = false;
          if (lhs.length <= rhs.length && lhs.height
              <= rhs.height && lhs.breadth <= rhs.breadth)
          {
              status = true;
          }
          return status;
      }

      public static bool operator >=(Box lhs, Box rhs)
      {
          bool status = false;
          if (lhs.length >= rhs.length && lhs.height
             >= rhs.height && lhs.breadth >= rhs.breadth)
          {
              status = true;
          }
          return status;
      }
      public override string ToString()
      {
          return String.Format("({0}, {1}, {2})", length, breadth, height);
      }
   
   }
   
   class Tester
   {
      static void Main(string[] args)
      {
        Box Box1 = new Box();          // 聲明 Box1,類型為 Box
        Box Box2 = new Box();          // 聲明 Box2,類型為 Box
        Box Box3 = new Box();          // 聲明 Box3,類型為 Box
        Box Box4 = new Box();
        double volume = 0.0;   // 體積

        // Box1 詳述
        Box1.setLength(6.0);
        Box1.setBreadth(7.0);
        Box1.setHeight(5.0);

        // Box2 詳述
        Box2.setLength(12.0);
        Box2.setBreadth(13.0);
        Box2.setHeight(10.0);

       // 使用重載的 ToString() 顯示兩個盒子
        Console.WriteLine("Box1: {0}", Box1.ToString());
        Console.WriteLine("Box2: {0}", Box2.ToString());
       
        // Box1 的體積
        volume = Box1.getVolume();
        Console.WriteLine("Box1 的體積: {0}", volume);

        // Box2 的體積
        volume = Box2.getVolume();
        Console.WriteLine("Box2 的體積: {0}", volume);

        // 把兩個對象相加
        Box3 = Box1 + Box2;
        Console.WriteLine("Box3: {0}", Box3.ToString());
        // Box3 的體積
        volume = Box3.getVolume();
        Console.WriteLine("Box3 的體積: {0}", volume);

        //comparing the boxes
        if (Box1 > Box2)
          Console.WriteLine("Box1 大於 Box2");
        else
          Console.WriteLine("Box1 不大於 Box2");
        if (Box1 < Box2)
          Console.WriteLine("Box1 小於 Box2");
        else
          Console.WriteLine("Box1 不小於 Box2");
        if (Box1 >= Box2)
          Console.WriteLine("Box1 大於等於 Box2");
        else
          Console.WriteLine("Box1 不大於等於 Box2");
        if (Box1 <= Box2)
          Console.WriteLine("Box1 小於等於 Box2");
        else
          Console.WriteLine("Box1 不小於等於 Box2");
        if (Box1 != Box2)
          Console.WriteLine("Box1 不等於 Box2");
        else
          Console.WriteLine("Box1 等於 Box2");
        Box4 = Box3;
        if (Box3 == Box4)
          Console.WriteLine("Box3 等於 Box4");
        else
          Console.WriteLine("Box3 不等於 Box4");

        Console.ReadKey();
      }
    }
}

當上面的代碼被編譯和執行時,它會產生下列結果:

Box1: (6, 7, 5) Box2: (12, 13, 10) Box1 的體積: 210 Box2 的體積: 1560 Box3:(18, 20, 15) Box3 的體積: 5400 Box1 不大於 Box2 Box1 小於 Box2 Box1 不大於等於 Box2 Box1 小於等於 Box2 Box1 不等於 Box2 Box3 等於 Box4

五、動態多態性

C# 允許您使用關鍵字 abstract 創建抽象類,用於提供接口的部分類的實現。當一個派生類繼承自該抽象類時,實現即完成。 抽象類 包含抽象方法,抽象方法可被派生類實現。派生類具有更專業的功能。

請註意,下面是有關抽象類的一些規則:

  • 不能創建一個抽象類的實例。
  • 不能在一個抽象類外部聲明一個抽象方法。
  • 通過在類定義前面放置關鍵字 sealed,可以將類聲明為 密封類 。當一個類被聲明為 sealed 時,它不能被繼承。抽象類不能被聲明為 sealed

下面的程序演示瞭一個抽象類:

實例:

using System;
namespace PolymorphismApplication
{
   abstract class Shape
   {
       abstract public int area();
   }
   class Rectangle:  Shape
   {
      private int length;
      private int width;
      public Rectangle( int a=0, int b=0)
      {
         length = a;
         width = b;
      }
      public override int area ()
      {
         Console.WriteLine("Rectangle 類的面積:");
         return (width * length);
      }
   }

   class RectangleTester
   {
      static void Main(string[] args)
      {
         Rectangle r = new Rectangle(10, 7);
         double a = r.area();
         Console.WriteLine("面積: {0}",a);
         Console.ReadKey();
      }
   }
}

當上面的代碼被編譯和執行時,它會產生下列結果:

Rectangle 類的面積: 面積: 70

當有一個定義在類中的函數需要在繼承類中實現時,可以使用 虛方法

虛方法是使用關鍵字 virtual 聲明的。

虛方法可以在不同的繼承類中有不同的實現。

對虛方法的調用是在運行時發生的。

動態多態性是通過 抽象類虛方法 實現的。

以下實例創建瞭 Shape 基類,並創建派生類 CircleRectangleTriangleShape 類提供一個名為 Draw 的虛擬方法,在每個派生類中重寫該方法以繪制該類的指定形狀。

實例:

using System;
using System.Collections.Generic;

public class Shape
{
    public int X { get; private set; }
    public int Y { get; private set; }
    public int Height { get; set; }
    public int Width { get; set; }
   
    // 虛方法
    public virtual void Draw()
    {
        Console.WriteLine("執行基類的畫圖任務");
    }
}

class Circle : Shape
{
    public override void Draw()
    {
        Console.WriteLine("畫一個圓形");
        base.Draw();
    }
}
class Rectangle : Shape
{
    public override void Draw()
    {
        Console.WriteLine("畫一個長方形");
        base.Draw();
    }
}
class Triangle : Shape
{
    public override void Draw()
    {
        Console.WriteLine("畫一個三角形");
        base.Draw();
    }
}

class Program
{
    static void Main(string[] args)
    {
        // 創建一個 List<Shape> 對象,並向該對象添加 Circle、Triangle 和 Rectangle
        var shapes = new List<Shape>
        {
            new Rectangle(),
            new Triangle(),
            new Circle()
        };

        // 使用 foreach 循環對該列表的派生類進行循環訪問,並對其中的每個 Shape 對象調用 Draw 方法
        foreach (var shape in shapes)
        {
            shape.Draw();
        }

        Console.WriteLine("按下任意鍵退出。");
        Console.ReadKey();
    }

}

當上面的代碼被編譯和執行時,它會產生下列結果:

  • 畫一個長方形
  • 執行基類的畫圖任務
  • 畫一個三角形
  • 執行基類的畫圖任務
  • 畫一個圓形
  • 執行基類的畫圖任務
  • 按下任意鍵退出。

下面的程序演示通過虛方法 area() 來計算不同形狀圖像的面積:

實例:

using System;
namespace PolymorphismApplication
{
   class Shape
   {
      protected int width, height;
      public Shape( int a=0, int b=0)
      {
         width = a;
         height = b;
      }
      public virtual int area()
      {
         Console.WriteLine("父類的面積:");
         return 0;
      }
   }
   class Rectangle: Shape
   {
      public Rectangle( int a=0, int b=0): base(a, b)
      {

      }
      public override int area ()
      {
         Console.WriteLine("Rectangle 類的面積:");
         return (width * height);
      }
   }
   class Triangle: Shape
   {
      public Triangle(int a = 0, int b = 0): base(a, b)
      {
     
      }
      public override int area()
      {
         Console.WriteLine("Triangle 類的面積:");
         return (width * height / 2);
      }
   }
   class Caller
   {
      public void CallArea(Shape sh)
      {
         int a;
         a = sh.area();
         Console.WriteLine("面積: {0}", a);
      }
   }  
   class Tester
   {
     
      static void Main(string[] args)
      {
         Caller c = new Caller();
         Rectangle r = new Rectangle(10, 7);
         Triangle t = new Triangle(10, 5);
         c.CallArea(r);
         c.CallArea(t);
         Console.ReadKey();
      }
   }
}

當上面的代碼被編譯和執行時,它會產生下列結果:

Rectangle 類的面積: 面積:70 Triangle 類的面積: 面積:25

總結💬

到此這篇關於C# 最基礎知識介紹–多態的文章就介紹到這瞭,更多相關C# 多態內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!

推薦閱讀: