ポリモーフィズムはもう使っている 〜WinFormsで理解するやさしい導入〜

ポリモーフィズムとは何か

ポリモーフィズム(多態性)という言葉を聞くと、

  • 難しそう
  • virtual / override が出てきそう
  • 結局なにが嬉しいの?

と感じやすいです。

ですが安心してください。

みなさんは、すでにポリモーフィズムを使っています。

今回はそれに「気づく」ことが目的です。

ポリモーフィズムとは、

「型をそろえて扱える」こと

です。

もう少しやさしく言うと、

見た目(扱い方)は同じなのに、中身(実体)が違っても動く

ということです。

ポイントはここです。

  • 親の型(ButtonやControl)でまとめて扱える
  • でも実体は、MyButtonだったり、普通のButtonだったりする

すでにWinFormsで使っている例(sender)

WinFormsでよく見るこれ。

private void HelloButtonClieked(object sender, EventArgs e)
{
}

この sender は object型 です。

つまりイベント側はこう言っています。

「押された部品が何かは固定しない。とにかく object として渡す」

でも実際には、

  • Buttonが押されれば、senderの中身はButton
  • MyButtonが押されれば、senderの中身はMyButton

になります。

“中身は違うのに、同じ受け取り方で処理できる”

これが、すでに使っているポリモーフィズムです。


「Buttonとして扱う」=ポリモーフィズム

次のように書けます。

Button b = new MyButton();

b は Button型 です。

でも中身は MyButton です。

ここが大事です。

  • 変数の型は Button
  • 実体は MyButton

「MyButtonなのに、Buttonとして使える」

これがポリモーフィズムの入口です。


自分たちでも作れる(MyButton)

たとえば、ボタンに「カテゴリ」を持たせたいとします。

public class MyButton : Button
{
    public string Category { get; set; }
}

Buttonの機能はそのまま。

でも自分専用の情報(Category)を追加できます。

この

“追加してもButtonとして扱える”

という性質が、ポリモーフィズムにつながります。


今はここまでで十分

ポリモーフィズムは本来、

  • virtual
  • override
  • 抽象クラス
  • インターフェース

などにつながります。

ですが、今はやりません。

今理解してほしいのはこれです。

  • 「型をそろえて扱える」ことがポリモーフィズム
  • WinFormsのsenderですでに起きている
  • Button b = new MyButton(); がもうポリモーフィズム

まとめ

  • ポリモーフィズムは 「型をそろえて扱える」こと
  • WinFormsの sender は中身が違っても同じ受け取り方をしている
  • Button b = new MyButton(); がすでにポリモーフィズム

ポリモーフィズムは「新しい山」ではありません。

WinFormsの中で、すでに毎日使っています。


サンプルコード(Form1.cs / MyButton.cs)

Form1.cs

using System;
using System.Windows.Forms;

namespace HelloWorld
{
    // Formクラスを継承した画面クラス(デザイナー対象)
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();

            // 普通のButton
            Button normalButton = new Button();
            normalButton.Parent = this;
            normalButton.Text = "普通のButton";
            normalButton.Left = 20;
            normalButton.Top = 20;
            normalButton.Click += HelloButtonClieked;

            // MyButton(中身はMyButtonだが、Buttonとしても扱える)
            MyButton myButton = new MyButton();
            myButton.Parent = this;
            myButton.Text = "MyButton";
            myButton.Category = "カテゴリA";
            myButton.Left = 20;
            myButton.Top = 60;
            myButton.Click += HelloButtonClieked;

            // どちらも同じイベントに接続できる(扱い方がそろっている)
        }

        private void HelloButtonClieked(object sender, EventArgs e)
        {
            // senderはobjectだが、実体はButton系
            Button pushed = (Button)sender;

            // Buttonなら共通で使える
            helloLabel.Text = "押されたのは: " + pushed.Text;

            // MyButtonなら追加情報も取り出せる
            if (sender is MyButton my)
            {
                helloLabel.Text += " / Category: " + my.Category;
            }
        }
    }
}

MyButton.cs

using System.Windows.Forms;

namespace HelloWorld
{
    // Buttonを継承して、情報を追加した自作ボタン
    public class MyButton : Button
    {
        public string Category { get; set; }
    }
}

訪問数 23 回, 今日の訪問数 23回

記事下広告