ポリモーフィズムはもう使っている 〜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; }
}
}




ディスカッション
コメント一覧
まだ、コメントがありません