English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

C# 多様性

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

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

ポリモーフィズムは静的または動的です。次に:静的多態性中、関数の応答はコンパイル時に発生します。次に:動的多態性中、関数の応答は実行時に発生します。

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 w3codebox");
         Console.ReadKey();
      }
   }
}

上記のコードがコンパイルおよび実行された場合、以下の結果が得られます:

整数を出力します: 1
浮点型を出力します: 1.23
文字列を表示します: Hello w3codebox

動的多態性

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("長方形の面積:");
         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("長方形の面積:");
         return (width * height); 
      }
   }
   class Triangle: Shape
   {}}
      public Triangle(int a = 0, int b = 0): base(a, b)
      {}}
      
      }
      public override int area()
      {}}
         Console.WriteLine("三角形の面積:");
         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