1. 程式人生 > 實用技巧 >c#多型性

c#多型性

C#多型性

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

多型性意味著有多重形式。在面向物件程式設計正規化中,多型性往往表現為"一個介面,多個功能"。

多型性可以是靜態的或動態的。在靜態多型性中,函式的響應是在編譯時發生的。在動態多型性中,函式的響應是在執行時發生的。

在 C# 中,每個型別都是多型的,因為包括使用者定義型別在內的所有型別都繼承自 Object

多型就是同一個介面,使用不同的例項而執行不同操作,如圖所示:

靜態多型性

在編譯時,函式和物件的連線機制被稱為早期繫結,也被稱為靜態繫結。C# 提供了兩種技術來實現靜態多型性。分別為:

  • 函式過載
  • 運算子過載

運算子過載將在下一章節討論,接下來我們將討論函式過載。

函式過載

您可以在同一個範圍內對相同的函式名有多個定義。函式的定義必須彼此不同,可以是引數列表中的引數型別不同,也可以是引數個數不同。不能過載只有返回型別不同的函式宣告

下面的例項演示了幾個相同的函式Add(),用於對不同個數引數進行相加處理:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace week2._1
{
    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 Test { static void Main(string[] args) { TestData data = new TestData();
int add1 = data.Add(1, 2, 3); int add2 = data.Add(1, 2); Console.WriteLine("三個值的和" + add1); Console.WriteLine("兩個值的和" + add2); Console.ReadKey(); } } }

結果:

三個值的和6
兩個值的和3

動態多型性

抽象類:

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

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

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

下面的程式演示了一個抽象類:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace week2._1
{
    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 基類,並建立派生類 Circle、 Rectangle、Triangle, Shape 類提供一個名為 Draw 的虛擬方法,在每個派生類中重寫該方法以繪製該類的指定形狀。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace week2._1
{
    public class Shape
    {
        public int X { get; private set; }
        public int Y { get; private set; }
        public int Width { get; set; }
        public int Height { 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 Test
    {
        static void Main(string[] args)
        {
            //建立一個list<shape>物件,並往該物件新增circle、rectangle、triangle
            var shapes = new List<Shape>
            {
                new Circle(),
                new Rectangle(),
                new Triangle()
            };
            //使用foreach迴圈對該列表的派生類進行迴圈訪問,並對每個shape呼叫draw方法
            foreach(var shape in shapes)
            {
                shape.Draw();
            }
            Console.WriteLine("按任意鍵退出");
            Console.ReadKey();
        }
    }
}

結果:

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

多型:一個介面多個功能。

靜態多型性:編譯時發生函式響應(呼叫);

動態多型性:執行時發生函式響應。

靜態繫結(早期繫結):編譯時函式和物件的連線機制。 兩種技術實現靜態多型性:函式過載/運算子過載。

函式過載:在同一範圍內對相同函式名有多個定義,可以是引數型別或引數個數的不同,但不許只有返回值型別不同。

運算子過載:

virtual和abstract都是用來修飾父類的,通過覆蓋父類的定義,讓子類重新定義

  • 1.virtual修飾的方法必須有實現(哪怕是僅僅新增一對大括號),而abstract修飾的方法一定不能實現
  • 2.virtual可以被子類重寫,而abstract必須被子類重寫。
  • 3.如果類成員被abstract修飾,則該類前必須新增abstract,因為只有抽象類才可以有抽象方法。
  • 4.無法建立abstract類的例項,只能被繼承無法例項化。

抽象類和虛方法共同實現動態多型性。

重寫(override)是用於重寫基類的虛方法,這樣在派生類中提供一個新的方法

過載(overload)是提供了一種機制, 相同函式名通過不同的返回值型別以及引數來表來區分的機制。

抽象方法和虛方法的區別

  • 1.虛方法必須有實現部分,抽象方法沒有提供實現部分,抽象方法是一種強制派生類覆蓋的方法,否則派生類將不能被例項化。
  • 2.抽象方法只能在抽象類中宣告,虛方法不是。如果類包含抽象方法,那麼該類也是抽象的,也必須宣告類是抽象的。
  • 3.抽象方法必須在派生類中重寫,這一點和介面類似,虛方法不需要再派生類中重寫。

簡單說,抽象方法是需要子類去實現的。虛方法是已經實現了的,可以被子類覆蓋,也可以不覆蓋,取決於需求。

抽象方法和虛方法都可以供派生類重寫。