C# 多态性

ポリモーフィズムとは、同じ動作が複数の異なる表現形式や形態を持つ能力です。

多态性複数の形式を持つことを意味します。オブジェクト指向プログラミングのパラダイムでは、ポリモーフィズムはしばしば「1つのインターフェース、複数の機能」として現れます。

ポリモーフィズムには静的または動的なものがあります。静态多态性では、関数の応答はコンパイル時に発生します。动态多态性中で、関数の応答は実行時に発生します。

C# では、すべての型がポリモーフィックです。ユーザー定義型を含むすべての型が Object を継承するためです。

ポリモーフィズムとは、同じインターフェースでも、異なるインスタンスを使用すると異なる操作を実行することです。図に示すように:

現実の例として、F1 キーを押すという動作を考えてみましょう。

  • 現在Flashインターフェースの下でポップアップするのはAS 3のヘルプドキュメントです;
  • 現在Wordの下でポップアップするのはWordヘルプです;
  • Windowsの下でポップアップするのはWindowsヘルプとサポートです。

同じイベントが異なるオブジェクトで発生すると、異なる結果が生じます。

静态多态性

コンパイル時における関数とオブジェクトの結び付けの仕組みは、アーリーバインディング(静的バインディング)と呼ばれます。C# では、静的ポリモーフィズムを実現するために2つの技術が提供されています。それは次のとおりです。

  • 函数重载
  • 运算符重载

演算子のオーバーロードは次の章で説明します。ここでは関数のオーバーロードについて説明します。


函数重载

同じスコープ内で、同じ関数名に対して複数の定義を持つことができます。関数の定義は互いに異なる必要があり、パラメータリストのパラメータ型が異なるか、パラメータの数が異なる必要があります。オーバーロードで戻り値の型だけが異なる関数宣言はできません。

以下のインスタンスはいくつかの同じ関数をデモンストレーションします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 サンプル");
         Console.ReadKey();
      }
   }
}

上記のコードがコンパイルおよび実行されると、次の結果が生成されます:

输出整型: 1
输出浮点型: 1.23
输出字符串: Hello サンプル

动态多态性

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 基底クラスを作成し、派生クラス Circle、Rectangle、Triangle を作成します。Shape クラスには 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
其他扩展