抽象クラス、抽象メソッドを利用するコードを紹介します。
基本のクラスに実装がないメソッドを定義し、派生されたクラスで実装をすることができます。基本のクラスに定義した実装がないメソッドを「抽象メソッド」と呼び、抽象メソッドのあるクラスを「抽象クラス」と呼びます。この記事では、抽象クラスや抽象メソッドを利用するコードを紹介します。
抽象クラスは以下の書式で定義します。
abstract (アクセス識別子) class (クラス名)
{
/* クラスの実装 */
}
抽象メソッドは抽象クラス内に実装します。
abstract (アクセス識別子) class (クラス名)
{
abstract (アクセス識別子) (戻り値の型) (メソッド名) (引数);
/* クラスの実装 */
}
abstract public class AbstractClass
{
public abstract int Operation();
public abstract int Proc(int value);
}
Windowsフォームアプリケーションを作成します。
下図のUIを作成します。テキストボックスを3つボタンを一つ配置します。
下記のコードを記述します。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace AbstractClassMethod
{
abstract public class BaseClass
{
public int input_a { get; set; }
public int input_b { get; set; }
public abstract int Operation();
public int AddAB()
{
return input_a + input_b;
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace AbstractClassMethod
{
public class OpAdd : BaseClass
{
public override int Operation()
{
return base.input_a + base.input_b;
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace AbstractClassMethod
{
public class OpSub : BaseClass
{
public override int Operation()
{
return base.input_a - base.input_b;
}
}
}
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace AbstractClassMethod
{
public partial class FormSimpleAbstract : Form
{
public FormSimpleAbstract()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
OpAdd oa = new OpAdd();
oa.input_a = Convert.ToInt32(textBox1.Text);
oa.input_b = Convert.ToInt32(textBox2.Text);
int ret = oa.Operation();
textBox3.Text = ret.ToString();
}
private void button2_Click(object sender, EventArgs e)
{
OpSub oa = new OpSub();
oa.input_a = Convert.ToInt32(textBox1.Text);
oa.input_b = Convert.ToInt32(textBox2.Text);
int ret = oa.Operation();
textBox3.Text = ret.ToString();
}
}
}
BaseClassが基本のクラスとなる抽象クラスです。BaseClassには値を格納する2つのプロパティ input_a, input_b が定義されています。また Operation() メソッドが抽象メソッドとして定義されています。通常のメソッドとしてAddAB() メソッドも定義されています。
OpAdd, OpSub はBaseClassを継承するクラスです。BaseClassクラスを継承しているため、OpAdd, OpSub クラスではOperation() メソッドの実装が必要になります。OpAddクラスのOperation()メソッドでは、input_a, input_b の和を戻り値として返す処理を、OpSubクラスのOperation() メソッドでは、input_a, input_b の差を戻り値として返す実装をしています。
フォームではボタンをクリックした際の処理を記述します。button1では OpAddクラスのインスタンスを作成し、テキストボックスに入力された数値を input_a, input_b に設定します。その後Operationメソッドを呼び出し input_a, input_b の和の値を求め、結果を下部のテキストボックスに表示します。
同様に button2では OpSubクラスのインスタンスを作成し、テキストボックスに入力された数値を input_a, input_b に設定します。その後Operationメソッドを呼び出し input_a, input_b の差の値を求め、結果を下部のテキストボックスに表示します。
private void button1_Click(object sender, EventArgs e)
{
OpAdd oa = new OpAdd();
oa.input_a = Convert.ToInt32(textBox1.Text);
oa.input_b = Convert.ToInt32(textBox2.Text);
int ret = oa.Operation();
textBox3.Text = ret.ToString();
}
private void button2_Click(object sender, EventArgs e)
{
OpSub oa = new OpSub();
oa.input_a = Convert.ToInt32(textBox1.Text);
oa.input_b = Convert.ToInt32(textBox2.Text);
int ret = oa.Operation();
textBox3.Text = ret.ToString();
}
プロジェクトを実行します。下図のウィンドウが表示されます。
上部のテキストボックス (textBox1, textBox2) に数値の値を入力します。
値の入力後[button1]をクリックします、textBox1, textBox2 に入力された値の和が下部のテキストボックス (textBox3) に表示されます。
同様に[button2]をクリックします。textBox1, textBox2 に入力された値の差が下部のテキストボックス (textBox3) に表示されます。
上記の実装で動作が確認できましたが、上記のコードでは抽象クラスによるメリットがあまりよくわからないかと思われます。
抽象クラスのメリットの一部がわかるような下記のプログラムを紹介します。
下図のUIを作成します。先のフォームからボタンを一つ減らし、RadioButtonを2つ配置します。
下記のコードを記述します。なお、BaseClass, OpAdd, OpSub クラスは先ほどのコードを利用します。
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace AbstractClassMethod
{
public partial class FormCastAbstract : Form
{
public FormCastAbstract()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
BaseClass op;
if (radioButton1.Checked == true) {
op = new OpAdd();
}
else {
op = new OpSub();
}
op.input_a =Convert.ToInt32(textBox1.Text);
op.input_b = Convert.ToInt32(textBox2.Text);
int result = op.Operation();
textBox3.Text = result.ToString();
}
}
}
OpAdd, OpSub を格納するクラス変数を宣言しますが、この変数を継承元のクラスであるBaseClass型で宣言します。BaseClass型で宣言すると派生型のOpAddクラス、OpSubクラスどちらのインスタンスも代入できます。
BaseClass op;
ラジオボタンのチェック状態に応じてインスタンスを作成するクラスを変更します。上側のRadioButton1にチェックがされている場合はop変数に OpAddクラスのインスタンスを作成して代入します。RadioButton2にチェックがある場合は、OpSubクラスのインスタンスを作成して代入します。
if (radioButton1.Checked == true) {
op = new OpAdd();
}
else {
op = new OpSub();
}
input_a, input_b プロパティにテキストボックスに入力された値を設定します。値の設定後、Operation() メソッドを呼び出して計算をします。Operation メソッドの戻り値を下部のテキストボックスに表示します。
op.input_a =Convert.ToInt32(textBox1.Text);
op.input_b = Convert.ToInt32(textBox2.Text);
int result = op.Operation();
textBox3.Text = result.ToString();
プロジェクトを実行します。下図のウィンドウが表示されます。
上部のテキストボックスに数値を入力します。
[radioButton1]にチェックがされている状態で[button1]をクリックします。下部のテキストボックスに入力した数値の和が表示されます。
[ratioButton2]をチェックしてクリックすると、入力した数値の差が下部のテキストボックスに表示されます。
同じコードで同じメソッドの呼び出しでも、抽象クラスと抽象メソッドを利用することで、別の処理を実行させることができます。