[C#] 20. オブジェクト指向プログラミング(OOP)の4つの原則(カプセル化、抽象化、継承化、多相化(ポリモーフィズム))
こんにちは。明月です。
この投稿はC#のオブジェクト指向プログラミング(OOP)の4つの原則(カプセル化、抽象化、継承化、多相化(ポリモーフィズム))に関する説明です。
オブジェクト指向プログラミング(Object-Oriented Programming)とはプログラミングの方法の一つです。プログラミングの方法とは、プログラムを開発する時にどの目的の中心に開発しようということの意味です。
その中でオブジェクト指向はオブジェクト(Object)を中心にプログラムを設計、開発することの意味です。
例えば、「業務計画書作成 -> 計画実行 -> テスト -> 結果確認 -> 報告書作成 -> 承認」のプロセスの業務があると思いましょう。
ここで、まず全体の業務単位(Controller)で構成して計画データ(Object)、テストデータ(Object)、結果データ(Object)、報告書データ(Object)、承認データ(Object)をプロセスの流れで配置します。
プログラム言語で考えば最小単位のクラスでオブジェクト(Object)を作成して管理することがオブジェクト指向プログラミング(Object-Oriented Programming)です。
ごのオブジェクト指向プログラミング(Object-Oriented Programming)には4つの原則がありますが、それがカプセル、抽象化、継承、多相化(ポリモーフィズム)です。
その4つの原則に関しては部分的に他の投稿で説明したことがあります。
link - [C#] 12. Staticとアクセス修飾子、そしてカプセル化
link - [C#] 15. インタフェース(interface)
link - [C#] 14. 抽象クラス(abstract)と抽象メソッド(abstract)、そして仮想関数(virtual)
link - [C#] 9. 関数(Method)とオーバーロード、再帰呼び出し
この投稿ではその特性をもっと詳細に説明します。
カプセル化
カプセル化はクラスのアクセスを制限することです。例えば、クラスのメンバー変数と関数がすべてpublic(すべてアクセス可能)で作成する場合、クラスの固有の特性がなくなります。
なので、クラスの特性を活かせるためにはクラスのデータ格納、取得する関数以外はprivate(内部だけアクセス可能)を設定することが正しいです。
using System;
using System.Collections.Generic;
namespace Example
{
// 国語クラス
class Japanese
{
// 点数変数
private int score;
// コンストラクタで点数を受け取る。
public Japanese(int score)
{
this.score = score;
}
}
// 英語クラス
class English
{
// 点数変数
private int score;
// コンストラクタで点数を受け取る。
public English(int score)
{
this.score = score;
}
}
// 数学クラス
class Math
{
// 点数変数
private int score;
// コンストラクタで点数を受け取る。
public Math(int score)
{
this.score = score;
}
}
// 学生クラス
class People
{
// 名前
private String name;
// 国語クラス
private Japanese japanese;
// 英語クラス
private English english;
// 数学クラス
private Math math;
// コンストラクタで名前と点数を受け取る。
public People(String name, int japanese, int english, int math)
{
this.name = name;
this.japanese = new Japanese(japanese);
this.english = new English(english);
this.math = new Math(math);
}
}
// 学校クラス
class SchoolClass
{
// 学校の人リスト
private List<People> peoples = new List<People>();
// 学生追加関数、名前と各成績を受け取る。
public void AddPeople(String name, int japanese, int english, int math)
{
// 学生追加
peoples.Add(new People(name, japanese, english, math));
}
}
class Program
{
// 実行関数
public static void Main(string[] args)
{
// 学校クラスのインスタンスを生成
SchoolClass schoolclass = new SchoolClass();
// 学生を追加する。
schoolclass.AddPeople("A", 50, 60, 70);
schoolclass.AddPeople("B", 70, 20, 50);
schoolclass.AddPeople("C", 60, 70, 40);
schoolclass.AddPeople("D", 30, 80, 30);
schoolclass.AddPeople("E", 50, 100, 50);
schoolclass.AddPeople("F", 70, 70, 60);
schoolclass.AddPeople("G", 90, 40, 40);
schoolclass.AddPeople("H", 100, 100, 90);
schoolclass.AddPeople("I", 40, 50, 10);
schoolclass.AddPeople("J", 60, 70, 30);
// 任意のキーを押してください
Console.WriteLine("Press any key...");
Console.ReadLine();
}
}
}
上のソースをみれば学校のクラスを生成して学生クラス、国語、英語、数学の成績のデータを格納しました。
ここでカプセルの特性を分かるために、総点と平均のデータを計算する関数を作成します。
using System;
using System.Collections.Generic;
using System.Linq;
namespace Example
{
// 国語クラス
class Japanese
{
// 点数変数
private int score;
// コンストラクタで点数を受け取る。
public Japanese(int score)
{
this.score = score;
}
// 点数取得関数
public int GetScore()
{
return this.score;
}
}
// 英語クラス
class English
{
// 点数変数
private int score;
// コンストラクタで点数を受け取る。
public English(int score)
{
this.score = score;
}
// 点数取得関数
public int GetScore()
{
return this.score;
}
}
// 数学クラス
class Math
{
// 点数変数
private int score;
// コンストラクタで点数を受け取る。
public Math(int score)
{
this.score = score;
}
// 点数取得関数
public int GetScore()
{
return this.score;
}
}
// 学生クラス
class People
{
// 名前
private String name;
// 国語クラス
private Japanese japanese;
// 英語クラス
private English english;
// 数学クラス
private Math math;
// 総点
private int total;
// 平均
private int avg;
// コンストラクタで名前と点数を受け取る。
public People(String name, int japanese, int english, int math)
{
this.name = name;
this.japanese = new Japanese(japanese);
this.english = new English(english);
this.math = new Math(math);
// 総点計算
this.total = japanese + english + math;
// 平均計算
this.avg = this.total / 3;
}
// 名前取得関数
public string GetName()
{
return this.name;
}
// 総点取得関数
public int GetTotal()
{
return this.total;
}
// 平均取得関数
public int GetAvg()
{
return this.avg;
}
// 成績順位計算
public int GetRank(List<People> peoples)
{
// 成績順位メンバー変数
int rank = 1;
foreach (People p in peoples.OrderByDescending(x => x.GetTotal()))
{
// 同じクラスならcontinue
if (p == this)
{
continue;
}
// 比較する対象が総点が高いなら本クラスの成績順位は下がる。
if (p.GetTotal() > this.GetTotal())
{
rank++;
}
}
// 成績順位
return rank;
}
}
// 学校クラス
class SchoolClass
{
// 学校の人リスト
private List<People> peoples = new List<People>();
// 学生追加関数、名前と各成績を受け取る。
public void AddPeople(String name, int japanese, int english, int math)
{
// 学生追加
peoples.Add(new People(name, japanese, english, math));
}
// 出力関数
public void Print()
{
// 学生の名前、総点平均、成績順位を出力する。
foreach (People p in peoples)
{
// コンソール出力
Console.WriteLine(p.GetName() + " total = " + p.GetTotal() + ", avg = " + p.GetAvg() + ", ranking = " + p.GetRank(peoples));
}
}
}
class Program
{
// 実行関数
public static void Main(string[] args)
{
// 学校クラスのインスタンスを生成
SchoolClass schoolclass = new SchoolClass();
// 学生を追加する。
schoolclass.AddPeople("A", 50, 60, 70);
schoolclass.AddPeople("B", 70, 20, 50);
schoolclass.AddPeople("C", 60, 70, 40);
schoolclass.AddPeople("D", 30, 80, 30);
schoolclass.AddPeople("E", 50, 100, 50);
schoolclass.AddPeople("F", 70, 70, 60);
schoolclass.AddPeople("G", 90, 40, 40);
schoolclass.AddPeople("H", 100, 100, 90);
schoolclass.AddPeople("I", 40, 50, 10);
schoolclass.AddPeople("J", 60, 70, 30);
// 出力
schoolclass.Print();
// 任意のキーを押してください
Console.WriteLine("Press any key...");
Console.ReadLine();
}
}
}
上の例をみればコンストラクタで国語、数学、英語の成績を受け取って総点と平均を計算します。
ここで私が総点と平均のメンバー変数のアクセス修飾子をpublicに設定すればどのようになるでしょう?
SchoolClassクラスで学生の成績修正が可能になります。この意味は学生(People)クラスのカプセルができなければ外部で修正が可能になるし、他のクラスでデータを修正することが可能になるとデータの無欠性がなくなります。つまり、データの信頼度が悪くなります。
また、総点と平均のデータを外部で計算することになるとプロジェクトが大きくなる時に学生の総点と平均をどこで計算することになるかを分からなくなります。学生クラスの独立性がなくなることです。
そのため、カプセル化に関してプログラマー(開発者)達は暗黙的に決めたルールがありますが、メンバー変数は必ずprivate、カプセルで必要な関数はpublic、その以外はprivate、拡張で必要な関数はprotectedに設定することです。
継承化
継承は似ているオブジェクト(Object)の縛って親クラス、インタフェースを定義して共通化します。その後、継承してオブジェクト(Object)をもっとシンプルに扱うことにします。
上の例をみればソースが少し長く見えます。成績クラスは特性が似ているクラスです。
継承特性でクラスを縛りましょう。
using System;
using System.Collections.Generic;
using System.Linq;
namespace Example
{
// 成績クラスのインタフェース
interface ISubject
{
int GetScore();
}
// 成績クラスの抽象クラス
abstract class AbstractSubject : ISubject
{
// 点数メンバー変数
private int score;
// コンストラクタで点数を受け取る。
public AbstractSubject(int score)
{
this.score = score;
}
// 点数取得関数
public int GetScore()
{
return this.score;
}
}
// 国語クラス
class Japanese : AbstractSubject
{
// コンストラクタ
public Japanese(int score) : base(score) { }
}
// 英語クラス
class English : AbstractSubject
{
// コンストラクタ
public English(int score) : base(score) { }
}
// 数学クラス
class Math : AbstractSubject
{
// コンストラクタ
public Math(int score) : base(score) { }
}
// 学生クラス
class People
{
// 名前
private String name;
// 0 - 国語, 1 - 英語, 2 - 数学
private List<ISubject> subjects = new List<ISubject>();
// 総点
private int total;
// 平均
private int avg;
// コンストラクタで名前と点数を受け取る。
public People(String name, int japanese, int english, int math)
{
this.name = name;
this.subjects.Add(new Japanese(japanese));
this.subjects.Add(new English(english));
this.subjects.Add(new Math(math));
// 総点計算
this.total = this.subjects.Sum(x => x.GetScore());
// 平均計算
this.avg = this.total / 3;
}
// 名前取得関数
public string GetName()
{
return this.name;
}
// 総点取得関数
public int GetTotal()
{
return this.total;
}
// 平均取得関数
public int GetAvg()
{
return this.avg;
}
// 成績順位計算
public int GetRank(List<People> peoples)
{
// 成績順位メンバー変数
int rank = 1;
foreach (People p in peoples.OrderByDescending(x => x.GetTotal()))
{
// 同じクラスならcontinue
if (p == this)
{
continue;
}
// 比較する対象が総点が高いなら本クラスの成績順位は下がる。
if (p.GetTotal() > this.GetTotal())
{
rank++;
}
}
// 成績順位
return rank;
}
}
// 学校クラス
class SchoolClass
{
// 学校の人リスト
private List<People> peoples = new List<People>();
// 学生追加関数、名前と各成績を受け取る。
public void AddPeople(String name, int japanese, int english, int math)
{
// 学生追加
peoples.Add(new People(name, japanese, english, math));
}
// 出力関数
public void Print()
{
// 学生の名前、総点平均、成績順位を出力する。
foreach (People p in peoples)
{
// コンソール出力
Console.WriteLine(p.GetName() + " total = " + p.GetTotal() + ", avg = " + p.GetAvg() + ", ranking = " + p.GetRank(peoples));
}
}
}
class Program
{
// 実行関数
public static void Main(string[] args)
{
// 学校クラスのインスタンスを生成
SchoolClass schoolclass = new SchoolClass();
// 学生を追加する。
schoolclass.AddPeople("A", 50, 60, 70);
schoolclass.AddPeople("B", 70, 20, 50);
schoolclass.AddPeople("C", 60, 70, 40);
schoolclass.AddPeople("D", 30, 80, 30);
schoolclass.AddPeople("E", 50, 100, 50);
schoolclass.AddPeople("F", 70, 70, 60);
schoolclass.AddPeople("G", 90, 40, 40);
schoolclass.AddPeople("H", 100, 100, 90);
schoolclass.AddPeople("I", 40, 50, 10);
schoolclass.AddPeople("J", 60, 70, 30);
// 出力
schoolclass.Print();
// 任意のキーを押してください
Console.WriteLine("Press any key...");
Console.ReadLine();
}
}
}
上の例は成績クラスでインタフェース(ISubject)を作成して、共通で使う関数(GetScore)を抽象クラス(AbstractSubject)で実装しました。
学生(People)クラスで各成績をリストで管理します。
もし、成績クラスが追加する時、抽象クラス(AbstractSubject)を継承してリストで追加することでオブジェクト(Object)を追加することが簡単になりました。
抽象化
抽象化は上の継承と関係があることですが、ここでは再定義(Override)に関して説明します。
上の例までは各成績は同じ点数で配点しましたが、仕様が変わって国語は100から120、英語は100から80に変わりました。
using System;
using System.Collections.Generic;
using System.Linq;
namespace Example
{
// 成績クラスのインタフェース
interface ISubject
{
int GetScore();
}
// 成績クラスの抽象クラス
abstract class AbstractSubject : ISubject
{
// 点数メンバー変数
private int score;
// コンストラクタで点数を受け取る。
public AbstractSubject(int score)
{
this.score = score;
}
// 点数取得関数
public virtual int GetScore()
{
return this.score;
}
}
// 国語クラス
class Japanese : AbstractSubject
{
// コンストラクタ
public Japanese(int score) : base(score) { }
// 点数関数の再定義
public override int GetScore()
{
// 100 -> 120
return (int)((float)base.GetScore() * 1.2f);
}
}
// 英語クラス
class English : AbstractSubject
{
// コンストラクタ
public English(int score) : base(score) { }
// 点数関数の再定義
public override int GetScore()
{
// 100 -> 80
return (int)((float)base.GetScore() * 0.8f);
}
}
// 数学クラス
class Math : AbstractSubject
{
// コンストラクタ
public Math(int score) : base(score) { }
}
// 学生クラス
class People
{
// 名前
private String name;
// 0 - 国語, 1 - 英語, 2 - 数学
private List<ISubject> subjects = new List<ISubject>();
// 総点
private int total;
// 平均
private int avg;
// コンストラクタで名前と点数を受け取る。
public People(String name, int japanese, int english, int math)
{
this.name = name;
this.subjects.Add(new Japanese(japanese));
this.subjects.Add(new English(english));
this.subjects.Add(new Math(math));
// 総点計算
this.total = this.subjects.Sum(x => x.GetScore());
// 平均計算
this.avg = this.total / 3;
}
// 名前取得関数
public string GetName()
{
return this.name;
}
// 総点取得関数
public int GetTotal()
{
return this.total;
}
// 平均取得関数
public int GetAvg()
{
return this.avg;
}
// 成績順位計算
public int GetRank(List<People> peoples)
{
// 成績順位メンバー変数
int rank = 1;
foreach (People p in peoples.OrderByDescending(x => x.GetTotal()))
{
// 同じクラスならcontinue
if (p == this)
{
continue;
}
// 比較する対象が総点が高いなら本クラスの成績順位は下がる。
if (p.GetTotal() > this.GetTotal())
{
rank++;
}
}
// 成績順位
return rank;
}
}
// 学校クラス
class SchoolClass
{
// 学校の人リスト
private List<People> peoples = new List<People>();
// 学生追加関数、名前と各成績を受け取る。
public void AddPeople(String name, int japanese, int english, int math)
{
// 学生追加
peoples.Add(new People(name, japanese, english, math));
}
// 出力関数
public void Print()
{
// 学生の名前、総点平均、成績順位を出力する。
foreach (People p in peoples)
{
// コンソール出力
Console.WriteLine(p.GetName() + " total = " + p.GetTotal() + ", avg = " + p.GetAvg() + ", ranking = " + p.GetRank(peoples));
}
}
}
class Program
{
// 実行関数
public static void Main(string[] args)
{
// 学校クラスのインスタンスを生成
SchoolClass schoolclass = new SchoolClass();
// 学生を追加する。
schoolclass.AddPeople("A", 50, 60, 70);
schoolclass.AddPeople("B", 70, 20, 50);
schoolclass.AddPeople("C", 60, 70, 40);
schoolclass.AddPeople("D", 30, 80, 30);
schoolclass.AddPeople("E", 50, 100, 50);
schoolclass.AddPeople("F", 70, 70, 60);
schoolclass.AddPeople("G", 90, 40, 40);
schoolclass.AddPeople("H", 100, 100, 90);
schoolclass.AddPeople("I", 40, 50, 10);
schoolclass.AddPeople("J", 60, 70, 30);
// 出力
schoolclass.Print();
// 任意のキーを押してください
Console.WriteLine("Press any key...");
Console.ReadLine();
}
}
}
抽象クラスでGetScore関数でvirtualキーワードを付けました。後で、国語、英語で配点を再定義しました。
単純に配点が変わることで総点、平均と成績順位が変わりました。オブジェクト指向プログラミング(OOP)で作成するとソースの拡張、修正が簡単になります。
多相化(ポリモーフィズム)
多相化(ポリモーフィズム)は同じ名の関数でパラメータの構造が違う関数を作成することです。
今回は既存のデータで選択成績を追加しましょう。
using System;
using System.Collections.Generic;
using System.Linq;
namespace Example
{
// 成績クラスのインタフェース
interface ISubject
{
int GetScore();
}
// 成績クラスの抽象クラス
abstract class AbstractSubject : ISubject
{
// 点数メンバー変数
private int score;
// コンストラクタで点数を受け取る。
public AbstractSubject(int score)
{
this.score = score;
}
// 点数取得関数
public virtual int GetScore()
{
return this.score;
}
}
// 国語クラス
class Japanese : AbstractSubject
{
// コンストラクタ
public Japanese(int score) : base(score) { }
// 点数関数の再定義
public override int GetScore()
{
// 100 -> 120
return (int)((float)base.GetScore() * 1.2f);
}
}
// 英語クラス
class English : AbstractSubject
{
// コンストラクタ
public English(int score) : base(score) { }
// 点数関数の再定義
public override int GetScore()
{
// 100 -> 80
return (int)((float)base.GetScore() * 0.8f);
}
}
// 数学クラス
class Math : AbstractSubject
{
// コンストラクタ
public Math(int score) : base(score) { }
}
// 選択クラス
class Select : AbstractSubject
{
// コンストラクタ
public Select(int score) : base(score) { }
}
// 学生クラス
class People
{
// 名前
private String name;
// 0 - 国語, 1 - 英語, 2 - 数学
private List<ISubject> subjects = new List<ISubject>();
// 総点
private int total;
// 平均
private int avg;
// コンストラクタで名前と点数を受け取る。
public People(String name, int japanese, int english, int math)
{
this.name = name;
this.subjects.Add(new Japanese(japanese));
this.subjects.Add(new English(english));
this.subjects.Add(new Math(math));
// 総点計算
this.total = this.subjects.Sum(x => x.GetScore());
// 平均計算
this.avg = this.total / this.subjects.Count;
}
// コンストラクタで名前と点数を受け取る。 (多相化(ポリモーフィズム))
public People(String name, int japanese, int english, int math, int select)
{
this.name = name;
this.subjects.Add(new Japanese(japanese));
this.subjects.Add(new English(english));
this.subjects.Add(new Math(math));
// 選択成績追加
this.subjects.Add(new Select(select));
// 総点計算
this.total = this.subjects.Sum(x => x.GetScore());
// 平均計算
this.avg = this.total / this.subjects.Count;
}
// 名前取得関数
public string GetName()
{
return this.name;
}
// 総点取得関数
public int GetTotal()
{
return this.total;
}
// 平均取得関数
public int GetAvg()
{
return this.avg;
}
// 成績順位計算
public int GetRank(List<People> peoples)
{
// 成績順位メンバー変数
int rank = 1;
foreach (People p in peoples.OrderByDescending(x => x.GetTotal()))
{
// 同じクラスならcontinue
if (p == this)
{
continue;
}
// 比較する対象が平均が高いなら本クラスの成績順位は下がる。(各、成績個数が違うので平均で比較)
if (p.GetAvg() > this.GetAvg())
{
rank++;
}
}
// 成績順位
return rank;
}
}
// 学校クラス
class SchoolClass
{
// 学校の人リスト
private List<People> peoples = new List<People>();
// 学生追加関数、名前と各成績を受け取る。
public void AddPeople(String name, int japanese, int english, int math)
{
// 学生追加
peoples.Add(new People(name, japanese, english, math));
}
// 多相化(ポリモーフィズム)として、既存のデータで選択成績を追加する。
public void AddPeople(String name, int korean, int english, int math, int select)
{
// 学生追加
peoples.Add(new People(name, korean, english, math, select));
}
// 出力関数
public void Print()
{
// 学生の名前、総点平均、成績順位を出力する。
foreach (People p in peoples)
{
// コンソール出力
Console.WriteLine(p.GetName() + " total = " + p.GetTotal() + ", avg = " + p.GetAvg() + ", ranking = " + p.GetRank(peoples));
}
}
}
class Program
{
// 実行関数
public static void Main(string[] args)
{
// 学校クラスのインスタンスを生成
SchoolClass schoolclass = new SchoolClass();
// 学生を追加する。
schoolclass.AddPeople("A", 50, 60, 70);
schoolclass.AddPeople("B", 70, 20, 50);
schoolclass.AddPeople("C", 60, 70, 40);
schoolclass.AddPeople("D", 30, 80, 30);
schoolclass.AddPeople("E", 50, 100, 50);
schoolclass.AddPeople("F", 70, 70, 60);
schoolclass.AddPeople("G", 90, 40, 40);
schoolclass.AddPeople("H", 100, 100, 90);
schoolclass.AddPeople("I", 40, 50, 10);
schoolclass.AddPeople("J", 60, 70, 30);
// 選択成績がある学生
schoolclass.AddPeople("K", 60, 70, 30, 70);
schoolclass.AddPeople("L", 60, 70, 30, 100);
// 出力
schoolclass.Print();
// 任意のキーを押してください
Console.WriteLine("Press any key...");
Console.ReadLine();
}
}
}
選択成績のクラスを追加しました。
そのことに対して、学校(SchoolClass)クラスのAddPeople関数も追加しました。多相化(ポリモーフィズム)で追加することで既存のソースは影響がないようにしました。
学生クラス(People)も多相化(ポリモーフィズム)でコンストラクタを追加しました。
成績順位は学生別で入力する個数が違うので平均で順位を計算することに修正しました。
最後に実行関数でKとLの学生を追加しました。
多相化(ポリモーフィズム)は既存のソースに影響がないようにソースを追加することが可能です。また、似ているな処理を同じ関数名で管理することも可能です。
つまり、ソース可読性がよくなるという意味です。
オブジェクト指向プログラミング(OOP)でプログラムを作成するとオブジェクト別でデータを区分するのでソースが読みやすくなります。また、仕様変更や追加があっても既存のソースを修正する範囲が少なくなります。
最近はデータ中心のプログラムが多いしビックデータで動くのでオブジェクト指向プログラミングはかなり重要になります。
でも、オブジェクト指向プログラミングも欠点があります。
上の例はすべてデータ重心で説明したので、すごく効率的に見えますが、すべてのプログラムがデータ中心ではありません。
例えば、ロードバランシングや画像チャットなどのデータ中心ではなく、プロセス中心になるプログラムだと逆にオブジェクト指向プログラミングは複雑になります。
理解しやい例ではWebサイトを作成する時にMVC(Model-View-Controller)形式で作成する時があります。
もちろん、データベースからデータを受け取ってクライアント(ブラウザ)にデータを表示することに考えばデータ中心だし、オブジェクト指向プログラミングが良いでしょう。
でも、Controllerの立場ならメンバー変数なしでただクライアント(ブラウザ)から要請を受け取って、そのデータによりデータベースからデータからデータを取得します。また、クライアント(ブラウザ)に応答します。
ただ、プロセス処理だけあることなので、要請URLより関数やクラスが増えることがあります。
なので、MVCプロジェクトをする時に、Beanデータ(要請データ)やEntityデータ(データベースデータ)などはインタフェースから抽象クラス、カプセル化などが良く片付けていますが、Controller場合は意味なしでクラスだけたくさんあることをよく見えます。
もちろん、その部分もデベロッパー(開発者)の能力により、どのように設定することで変わると思いますが、様々なプロジェクトを見るとそのようなケースが多いですね。
ここまでC#のオブジェクト指向プログラミング(OOP)の4つの原則(カプセル化、抽象化、継承化、多相化(ポリモーフィズム))に関する説明でした。
ご不明なところや間違いところがあればコメントしてください。
- [C#] 27. varキーワードとdynamicキーワード2019/07/16 20:41:27
- [C#] 26. 例外処理(try ~ catch)する方法2019/07/16 00:59:34
- [C#] 25. イベント(event)キーワードを使い方2019/07/16 00:48:03
- [C#] 24. ラムダ式(匿名関数)とAction、Func関数を使い方、そしてクロージャ(Closure)2019/07/16 00:36:19
- [C#] 23. デリゲート(delegate)2019/07/15 02:25:26
- [C#] 22. インデクサー(indexer)を使う方法2019/07/13 01:06:04
- [C#] 21. C#のプロパティ(Property)2019/07/13 00:56:20
- [C#] 20. オブジェクト指向プログラミング(OOP)の4つの原則(カプセル化、抽象化、継承化、多相化(ポリモーフィズム))2019/07/12 00:17:35
- [C#] 19. 列挙型(enum)を使う方法2019/07/11 23:13:25
- [C#] 18. 構造体(Struct)、そして値型を参照するタイプ(Reference of value type)と参照型を参照するタイプ(Reference of reference type)2019/07/10 23:57:25
- [C#] 17. thisとbaseのキーワード2019/07/10 23:43:56
- [C#] 16. 継承禁止のキーワードのsealed2019/07/10 00:19:18
- [C#] 15. インタフェース(interface)2019/07/10 00:06:17
- [C#] 14. 抽象クラス(abstract)と抽象メソッド(abstract)、そして仮想関数(virtual)2019/07/08 23:04:09
- [C#] 13. クラスの継承と再定義(override)する方法、overrideとnewの差異2019/07/08 22:55:00
- check2024/04/10 19:03:53
- [Java] 64.Spring bootとReactを連結する方法(Buildする方法)2022/03/25 21:02:18
- [Javascript] Node.jsをインストールしてReactを使う方法2022/03/23 18:01:34
- [Java] 63. Spring bootでcronスケジューラとComponentアノテーション2022/03/16 18:57:30
- [Java] 62. Spring bootでWeb-Filterを設定する方法(Spring Security)2022/03/15 22:16:37
- [Java] JWT(Json Web Token)を発行、確認する方法2022/03/14 19:12:58
- [Java] 61. Spring bootでRedisデータベースを利用してセッションクラスタリング設定する方法2022/03/01 18:20:52
- [Java] 60. Spring bootでApacheの連結とロードバランシングを設定する方法2022/02/28 18:45:48
- [Java] 59. Spring bootのJPAでEntityManagerを使い方2022/02/25 18:27:48
- [Java] 58. EclipseでSpring bootのJPAを設定する方法2022/02/23 18:11:10
- [Java] 57. EclipseでSpring bootを設定する方法2022/02/22 19:04:49
- [Python] Redisデータベースに接続して使い方2022/02/21 18:23:49
- [Java] Redisデータベースを接続して使い方(Jedisライブラリ)2022/02/16 18:13:17
- [C#] Redisのデータベースを接続して使い方2022/02/15 18:46:09
- [CentOS] Redisデータベースをインストールする方法とコマンドを使い方2022/02/14 18:33:07