静岡理工科大学 菅沼ホーム 目次 索引

第7章 クラスと継承

  1. 7.1 クラスと継承
    1. A. C++
    2. B. Java
    3. C. JavaScript
    4. D. PHP
    5. E. Ruby
    6. F. Python
    7. G. C#
    8. H. VB
  2. 6.2 クラスに対するプログラム例
    1. A. C++
    2. B. Java
    3. C. JavaScript
    4. D. PHP
    5. E. Ruby
    6. F. Python
    7. G. C#
    8. H. VB

7.1 クラスと継承

  大きなプログラムの場合,その部分的な機能の修正のため,他の機能に対応する部分も理解し,かつ,場合によってはそれらの一部も修正するなど,プログラム全体にわたって理解し,かつ,修正をしなければならないとしたら,大変なことになります.そこで,プログラムのモジュール化が非常に重要になります.各機能毎にモジュール化し,

  1. そのモジュール内部における詳細な処理を知らなくても,適当なインターフェースを介してデータを渡し,また,インターフェースを介して希望する結果が得られる.

  2. モジュールとのやりとりは,インターフェースを介してのみ可能であり,モジュールの外部から,そのモジュール内の処理を直接コントロールすることはできないし,また,コントロールする必要がない.

ようにしておけば,各モジュールは他のモジュールの影響を受けにくくなり,対応する機能の修正はそのモジュールの修正だけで済みます.ある意味では,各モジュールをブラックボックス化するわけです.

  このモジュール化の一つの実現方法が関数です.引数を付けて関数を呼ぶというインターフェースによって,関数内部の処理の詳細を知らなくても結果を得ることができます.また,ローカル変数の存在により,関数外部から関数内部の処理を直接コントロールすることは基本的に不可能です.

  このように,関数もモジュール化の強力な手段ですが,それは,アルゴリズムに重点を置いたブラックボックス化です.しかし,場合によっては,データに重点を置いたブラックボックス化が必要になる場合があります.それが,まさに,クラス( class )です.クラスでは,データとそれを扱う関数を一つにまとめ,特定のインターフェース(クラス内で宣言された関数)を介してのみ,その内部にアクセスできるようにしています.このような処理をデータの抽象化と呼び,抽象データ型の変数(つまり,あるクラス型として宣言された変数)をオブジェクト( object )(データとそれを操作する手続き-関数-をひとまとめにしたもの)と呼びます.

  また,先に説明しましたように,クラスとは,ある「もの」に対し,その「もの」に共通する特徴等をもとにして,形式的な定義を与えたものであるといえます.もう少しプログラミング的な感覚でいえば,「もの」に共通するデータと,それらのデータを処理する方法を記述した手続きの集まりです.例えば,「車」というクラスを定義したとすれば,車の構造を記述するデータと車を動かしたりするのに必要な手続きからなっているはずです.また,クラスは「もの」に対する抽象的な定義ですが,そのインスタンス(オブジェクトとなる)はクラスを具体化したものに相当します.例えば,「車」クラスの場合であれば,そのインスタンスは,ある特定の人が所有する特定の車になります.同じプログラムであっても,アルゴリズムに重点を置いたモジュール化を行うのか,または,データに重点を置いたモジュール化を行うのかによって,書き方はかなり異なってきます.問題によって,より適した方法があるはずです.常にクラスを使用すれば良いというわけではありません.

  クラスは,その定義の方法から見て,ユーザーが新たに定義する変数の型と考えても良いと思います.新しい変数の型を定義すれば,その型の操作方法も必要になります.例えば,実部と虚部という 2 つのデータからなる複素数に対応する型をクラスによって定義したとします.すると,単純な加算ですら,既存の方法,つまり,int 型や double 型と同じような方法を使用することができません.従って,定義した変数の加算をどのようにして実行するかについても定義してやる必要が出てきます.そこで,クラスの定義には,単にデータだけでなく,そのデータを取り扱う方法を記述した関数が必要になってくるわけです.

  Windows のプログラムを書くような場合について考えてみてください.多くの Windows アプリケーションが存在しますが,その基本的なレイアウトや機能はほとんど同じです.それらのすべてを一から記述するとすれば大変な作業になります.しかし,Windows の基本機能を実現したプログラムがすでに存在し,そのプログラムを利用しながら必要な箇所の修正,追加を行うことによって可能であるとすれば,作業量は非常に少なくなります.これを実現したのが継承( inheritance )です.あるクラスに宣言されている変数や関数をすべて受け継ぎ(継承し),それに新たな変数や関数を追加したり,継承した関数の内容を修正して新しいクラスを宣言することができます.

  以下に述べる各言語の定義方法の中に,privateprotectedpublic という言葉がしばしば出現します.言語によって,多少の違いがありますが,基本的な意味について述べておきます.これらは,変数や関数が,どの範囲から参照可能かを示す言葉であり,private 指定された変数や関数は,それらが定義されたクラス内の関数(メンバー関数)だけから参照可能であることを意味します.また,protected 指定された変数や関数は,それらが定義されたクラス及びそのクラスの派生クラス内の関数だけから参照可能であることを意味し,public 指定された変数や関数は,どこからでも参照可能であることを意味します.

  1. C++

      クラスの一般的定義方法は以下に示すとおりです.ただし,public,private 等に対応するすべてのメンバーを所有する必要はありませんし,また,所有する変数や関数の数に制限があるわけではありません.public 等を記述しないと,クラス宣言のメンバーがプライベートとみなされる点以外,記述する順番も一般的には決まっていません.また,他のクラスを継承しない場合は,クラス名の後ろから { の前までは記述する必要がありません.なお,他のクラスを継承した場合,そのクラスを派生クラスと呼びます.
    class クラス名 [ : [アクセス権] 基底クラス名 [,[アクセス権] 基底クラス名・・・]] {
    	private:
    		int x;                // プライベートメンバー変数
    		double fun1(int);     // プライベートメンバー関数
    	protected:
    		int y;                // 派生クラスだけが使用可能なメンバー変数
    		double fun2(int);     // 派生クラスだけが使用可能なメンバー関数
    	public:
    		int z;                // パブリックメンバー変数
    			// コンストラクタ
    		クラス名 (引数リスト) : 基底クラス名(パラメータリスト), ・・・
    		{
    			このクラスに必要な初期設定
    		}
    		double fun3(int);     // パブリックメンバー関数
    	friend double fun4(int); // フレンド関数
    	friend class Example2;   // フレンドクラス
    };
    			
      クラスのオブジェクトを他の変数に代入した場合,例えば,
    Example t1(1, 2);
    Example t2 = t1;
    Example *p1 = new Example(1, 2);
    Example *p2 = p1;
    			
    のような処理をした場合,第2章で述べたように,1 行目,2 行目の場合は,t1 を構成する全てのデータがコピーされて t2 に代入されるため,t1 と t2 は異なるオブジェクトとなります.ただし,クラス Example の中で new 演算子を使用している場合は,new 演算子によって得られたアドレスだけがコピーされ,そのアドレスが指す場所はコピーされませんので注意してください.また,3 行目,4 行目の場合は,p1 に記憶されてるアドレスがコピーされて p2 に代入されるため,p1 と p2 は同じオブジェクトを指すことになり,p1 を介してオブジェクト内の値を変更すれば,p2 を介した値も変化します(逆も同様).

  2. Java

      クラスの一般的定義方法は以下に示すとおりです.他のクラスを継承しない場合は extendsスーパークラス名を,インタフェースを継承しない場合は implements や親インタフェース名を記述する必要がありません(継承可能なクラスは 1 つだけだが,インタフェースは複数継承可).なお,他のクラスを継承した場合,そのクラスをサブクラスと呼びます.
    [クラス修飾子] class クラス名[ extends スーパークラス名] [implements 親インタフェース名 [ , ・・・ ]] {
    	[変数修飾子] データ型 変数名,・・・;
    		・・・・・
    		// コンストラクタ
    	クラス名 (...) {
    		super(...);   // スーパークラスのコンストラクタ
    		コンストラクタにおける処理
    	}
    		・・・・・
    	[関数修飾子] 関数の型 関数名 (引数の並び) {
    		関数における処理
    	}
    		・・・・・
    }
    			
      クラスのオブジェクトを他の変数に代入した場合,例えば,
    Example p1 = new Example(1, 2);
    Example p2 = p1;
    			
    のような処理をした場合,第2章で述べたように,p1 や p2 はポインタ変数としてとらえることができます.つまり,p1 に記憶されているアドレスがコピーされて p2 に代入されるため,p1 と p2 は同じオブジェクトを指すことになり,p1 を介してオブジェクト内の値を変更すれば,p2 を介した値も変化します(逆も同様).

  3. JavaScript

      JavaScript には,クラスという概念がありませんが,似た概念としてオブジェクトが存在します.下に示すのは,オブジェクト Complex の定義とそのメンバー関数(に相当する) add の例です.
    		// Complex オブジェクト
    function Complex(a, b)
    {
    	this.x = a;
    	this.y = b;
    }
    		// Complex オブジェクトのメンバー関数 add
    Complex.prototype.add = function(a, b)
    {
    	var cp = new Complex(a.x+b.x, a.y+b.y);
    	return cp;
    }
    			
      オブジェクトを他の変数に代入した場合,例えば,
    var p1 = new Example(1, 2);
    var p2 = p1;
    			
    のような処理をした場合,第2章で述べたように,p1 や p2 はポインタ変数としてとらえることができます.つまり,p1 に記憶されているアドレスがコピーされて p2 に代入されるため,p1 と p2 は同じオブジェクトを指すことになり,p1 を介してオブジェクト内の値を変更すれば,p2 を介した値も変化します(逆も同様).

  4. PHP

      クラスの一般的定義方法は以下に示すとおりです.他のクラスを継承しない場合は extends基底クラス名を記述する必要がありません(継承可能なクラスは 1 つだけ).なお,他のクラスを継承した場合,そのクラスを派生クラスと呼びます.
    class クラス名[ extends 基底クラス名] {
    	変数名,・・・;
    		・・・・・
    		// コンストラクタ
    	function クラス名 (...) {
    		parent::基底クラス名(...);   // 基底クラスクラスのコンストラクタ
    		コンストラクタにおける処理
    	}
    		・・・・・
    	function 関数名 (引数の並び) {
    		関数における処理
    	}
    		・・・・・
    }
    			
      クラスのオブジェクトを他の変数に代入した場合,例えば,
    $p1 = new Example(1, 2);
    $p2 = $p1;
    			
    のような処理をした場合,第2章で述べたように,p1 や p2 はポインタ変数としてとらえることができます.つまり,p1 に記憶されているアドレスがコピーされて p2 に代入されるため,p1 と p2 は同じオブジェクトを指すことになり,p1 を介してオブジェクト内の値を変更すれば,p2 を介した値も変化します(逆も同様).

  5. Ruby

      クラスの一般的定義方法は以下に示すとおりです.他のクラスを継承しない場合は < 以降を記述する必要がありません(継承可能なクラスは 1 つだけ).なお,他のクラスを継承した場合,そのクラスをサブクラスと呼びます.
    class クラス名 [ <  スーパークラス名 ]
    		// コンストラクタ
    	def initialize(...) {
    		super(...);   // スーパークラスのコンストラクタ
    		コンストラクタにおける処理
    	}
    		・・・・・
    	式(演算式,関数,クラスなど)
         ・・・ 
    end
    			
      クラスのオブジェクトを他の変数に代入した場合,例えば,
    p1 = Example.new(1, 2);
    p2 = p1;
    			
    のような処理をした場合,第2章で述べたように,p1 や p2 はポインタ変数としてとらえることができます.つまり,p1 に記憶されているアドレスがコピーされて p2 に代入されるため,p1 と p2 は同じオブジェクトを指すことになり,p1 を介してオブジェクト内の値を変更すれば,p2 を介した値も変化します(逆も同様).

  6. Python

      クラスの一般的定義方法は以下に示すとおりです.他のクラスを継承しない場合は,クラス名の後ろの括弧及びその内容を記述する必要がありません(多重継承可).なお,他のクラスを継承した場合,そのクラスを派生クラスと呼びます.
    class クラス名 [(基底クラス名,・・・)] : 
    	変数名
    		・・・・・
    		// コンストラクタ
    	def __init__(self,...) {
    		基底クラス名.__init__(self,...);   // 基底クラスのコンストラクタ
    		コンストラクタにおける処理
    	}
    		・・・・・
    	def 関数名 (self, 引数の並び) : 
    		関数における処理
    		・・・・・
    			
      クラスのオブジェクトを他の変数に代入した場合,例えば,
    p1 = Example(1, 2, 3)
    p2 = p1
    p3 = copy.copy(p1)
    p4 = copy.deepcopy(p1)
    			
    のような処理をした場合,第2章で述べたように,p1,p2,p3,p4 はポインタ変数としてとらえることができます.つまり,p1 に記憶されているアドレスがコピーされて p2 に代入されるため,p1 と p2 は同じオブジェクトを指すことになり,p1 を介してオブジェクト内の値を変更すれば,p2 を介した値も変化します(逆も同様).

      3 行目のように,p1 の浅いコピーを p3 に代入した場合は,クラスを構成する全てのデータがコピーされ,その場所を p3 が指すことになるため,p1 と p3 は異なるオブジェクトとなります.ただし,クラス Example の中で配列などを使用している場合は,配列などの場所を指すアドレスだけがコピーされ,配列自体はコピーされません.配列などを含めてコピーするためには,4 行目に示すように,深いコピーを使用する必要があります.なお,深いコピーは,以下に示すリスト構造のような場合に対しても,正しく動作します.
    # -*- coding: UTF-8 -*-
    
    import copy
    
    ############################
    # リスト構造               #
    #      coded by Y.Suganuma #
    ############################
    
    #*******************/
    # クラスListの定義 */
    #*******************/
    class List :
    			# コンストラクタ
    	def __init__(self, s = "") :
    		self.st   = s   # データ(文字列)
    		self.next = None   # 次のデータ
    
    	#*************************************/
    	# データの追加                       */
    	#      dt : Listクラスのオブジェクト */
    	#*************************************/
    	def add(self, dt) :
    		lt2 = self
    		sw  = 1
    		while sw > 0 :
    					# 最後に追加
    			if lt2.next == None :
    				lt2.next = dt
    				sw       = 0
    					# 比較し,途中に追加
    			else :
    				lt1 = lt2
    				lt2 = lt2.next
    				if dt.st < lt2.st :   # 追加
    					dt.next  = lt2
    					lt1.next = dt
    					sw       = 0
    
    	#********************/
    	# データの削除      */
    	#      st1 : 文字列 */
    	#********************/
    	def delete(self, st1) :
    		lt2 = self
    		sw  = 1
    		while sw > 0 :
    					# データが存在しない場合
    			if lt2.next == None :
    				print("      指定されたデータがありません!")
    				sw = 0
    					# 比較し,削除
    			else :
    				lt1 = lt2
    				lt2 = lt2.next
    				if st1 == lt2.st :   # 削除
    					lt1.next = lt2.next
    					sw       = 0
    
    	#*********************/
    	# リストデータの出力 */
    	#*********************/
    	def output(self) :
    		nt = self.next
    		while nt != None :
    			print("   data =", nt.st)
    			nt = nt.next
    
    name1 = List ()
    sw    = 1
    while sw > 0 :
    	str = input("1:追加,2:削除,3:出力,0:終了? ")
    	sw  = int(str)
    	if sw == 1 :   # 追加
    		str = input("   データを入力してください ")
    		lt  = List (str)
    		name1.add(lt)
    	elif sw == 2 :   # 削除
    		str = input("   データを入力してください ")
    		name1.delete(str)
    	elif sw == 3 :   # 出力
    		name1.output()
    	else :   # 終了
    		sw = 0
    name2 = name1
    name3 = copy.copy(name1)
    name4 = copy.deepcopy(name1)
    name1.delete("str")
    print("name1")
    name1.output()
    print("name2")
    name2.output()
    print("name3")
    name3.output()
    print("name4")
    name4.output()
    			

  7. C#

      クラスの一般的定義方法は以下に示すとおりです.他のクラスを継承しない場合は : 以下を記述する必要がありません(継承可能なクラスは 1 つだけ).なお,他のクラスを継承した場合,そのクラスを派生クラスと呼びます.

      クラス修飾子として,public (どこからでもアクセス可能),または,internal (同じアセンブリ単位からアクセス可能)を選択できます.省略すると,internal とみなされます.アセンブリ単位については,.NET に関するマニュアル等を参照してください.

      メンバー修飾子として,public (どこからでもアクセス可能),private (同じクラス内からアクセス可能),protected (同じクラス及びそのクラスを継承したクラスからアクセス可能),internal(同じアセンブリ単位からアクセス可能)などを選択できます.省略すると,private とみなされます.
    [ クラス修飾子 ] class クラス名 [  :  基底クラス名 ] {
    	[ メンバー修飾子 ] データ型 変数名,・・・;
    		・・・・・
    			// コンストラクタ
    	[ メンバー修飾子 ] クラス名(...) : base(..) {   // base は基底クラスのコンストラクタ
    		コンストラクタにおける処理
    	}
    		・・・・・
    	[ メンバー修飾子 ] 関数の型 関数名 (引数の並び) {
    		関数における処理
    	}
    		・・・・・
    }
    			
      クラスのオブジェクトを他の変数に代入した場合,例えば,
    Example p1 = new Example(1, 2);
    Example p2 = p1;
    			
    のような処理をした場合,第2章で述べたように,p1 や p2 はポインタ変数としてとらえることができます.つまり,p1 に記憶されているアドレスがコピーされて p2 に代入されるため,p1 と p2 は同じオブジェクトを指すことになり,p1 を介してオブジェクト内の値を変更すれば,p2 を介した値も変化します(逆も同様).

  8. VB

      クラスの一般的定義方法は以下に示すとおりです.他のクラスを継承しない場合は : 以下を記述する必要がありません(継承可能なクラスは 1 つだけ).なお,他のクラスを継承した場合,そのクラスを派生クラスと呼びます.

      修飾子として,Public (どこからでもアクセス可能),Private (同じクラス内からアクセス可能),Protected (同じクラス及びそのクラスを継承したクラスからアクセス可能),Friend(同じアセンブリ単位からアクセス可能)などを選択できます.変数に対する修飾子は必ず必要ですが,クラスや関数に対するアクセス権を省略すると,Friend とみなされます.アセンブリ単位については,.NET に関するマニュアル等を参照してください.
    [ 修飾子 ] Class クラス名
    	[ Inherits 基底クラス ; ]
    	修飾子 変数名 As データ型 ;
    		' コンストラクタ
    	[ [ 修飾子 ] Sub New (引数の並び)
    		[ MyBase.new(...) ]   ' 基底クラスのコンストラクタ
    		コンストラクタにおける処理
    	End Sub ]
    		・・・・・
    	[ 修飾子 ] Sub / Function 関数名 (引数の並び) [ As 戻り値のデータ型 ]
    		関数における処理
    	End Sub / Function
    		・・・・・
    End Class
    			
      クラスのオブジェクトを他の変数に代入した場合,例えば,
    Dim p1 As Example = new Example(1, 2)
    Dim p2 As Example = p1
    			
    のような処理をした場合,第2章で述べたように,p1 や p2 はポインタ変数としてとらえることができます.つまり,p1 に記憶されているアドレスがコピーされて p2 に代入されるため,p1 と p2 は同じオブジェクトを指すことになり,p1 を介してオブジェクト内の値を変更すれば,p2 を介した値も変化します(逆も同様).

7.2 クラスに対するプログラム例

  1. C++

    001	/******************************/
    002	/* クラスに対するプログラム例 */
    003	/*      coded by Y.Suganuma   */
    004	/******************************/
    005	#include <stdio.h>
    006	#include <iostream>
    007	#include <string>
    008	#include <vector>
    009	
    010	using namespace std;
    011	
    012	/**************/
    013	/* クラス Win */
    014	/**************/
    015	class Win {
    016			string BGC;   // 背景色
    017		protected :
    018			pair<int, int> size;   // サイズ(縦と横)
    019		public :
    020			static string name;   // 名前
    021			vector<string> menu;   // メニュー
    022				// コンストラクタ
    023			Win(string s1, string s2) {
    024				size = make_pair(100, 200);
    025				BGC  = "white";
    026				menu.push_back(s1);
    027				menu.push_back(s2);
    028			}
    029				// 名前の取得
    030			static string getName() { return name; }
    031				// 背景色の取得
    032			string getBGC();
    033				// サイズの取得
    034			pair<int, int> getSize() { return size; }
    035	};
    036	
    037	/****************/
    038	/* 背景色の取得 */
    039	/****************/
    040	string Win::getBGC()
    041	{
    042		return BGC;
    043	}
    044	
    045	/**************/
    046	/* クラス App */
    047	/**************/
    048	class App : public Win {   // クラス Win を継承
    049	//		string BGC;   // 背景色
    050		public :
    051				// コンストラクタ
    052			App(string s1, string s2) : Win(s1, s2) {
    053				menu.push_back("other");
    054			}
    055				// サイズの変更
    056			void setSize(int row, int col) { size = make_pair(row, col); }
    057				// 背景色の変更と参照(基底クラスの private 変数にアクセスできない)
    058	//		void setBGC(string col) { BGC = col; }
    059			string getBGC() {
    060	//			return BGC;
    061				return Win::getBGC();
    062			}
    063	};
    064	
    065	string Win::name = "Window1";   // static 指定のため必要
    066	
    067	int main()
    068	{
    069				// クラス Win
    070		cout << "Win_name : " << Win::name << endl;   // 名前,static 指定のため可
    071		cout << "Win_name : " << Win::getName() << endl;   // 名前,static 変数だけを参照可
    072		Win w1 = Win("file", "edit");
    073		cout << "w1_name : " << w1.name << endl;   // 名前
    074		cout << "w1_BGC : " << w1.getBGC() << endl;   // 背景色
    075		pair<int, int> s = w1.getSize();   // サイズの取得
    076		cout << "w1_size : " << s.first << " " << s.second << endl;
    077		cout << "w1_menu : " << w1.menu[0] << " " << w1.menu[1] << endl;   // メニュー
    078				// クラス App(クラス Win を継承)
    079		cout << endl << "App_name : " << App::name << endl;   // 名前,Win クラスと同じ
    080		App a1  = App("file", "edit");
    081		a1.name = "Window2";
    082		cout << "Win_name : " << Win::name << endl;   // 名前(Win)
    083		cout << "App_name : " << App::name << endl;   // 名前(App)
    084		cout << "a1_name : " << a1.name << endl;   // 名前(App)
    085	//	a1.setBGC("red");   // 基底クラスの private 変数にアクセスできない
    086		cout << "a1_BGC : " << a1.getBGC() << endl;   // 背景色
    087		a1.setSize(200, 400);   // サイズの変更
    088		s = a1.getSize();
    089		cout << "a1_size : " << s.first << " " << s.second << endl;
    090		cout << "w1_size : " << w1.getSize().first << " " << w1.getSize().second << endl;
    091		cout << "a1_menu : " << a1.menu[0] << " " << a1.menu[1] << " " << a1.menu[2] << endl;   // メニュー
    092				// new 演算子と代入
    093		App a2 = a1;
    094		cout << "\n前 a1_size : " << a1.getSize().first << " " << a1.getSize().second << endl;
    095		cout << "   a2_size : " << a2.getSize().first << " " << a2.getSize().second << endl;
    096		a1.setSize(300, 600);   // サイズの変更
    097		cout << "後 a1_size : " << a1.getSize().first << " " << a1.getSize().second << endl;
    098		cout << "   a2_size : " << a2.getSize().first << " " << a2.getSize().second << endl;
    099	
    100		App *b1 = new App("file", "edit");
    101		App *b2 = b1;
    102		cout << "前 b1_size : " << b1->getSize().first << " " << b1->getSize().second << endl;
    103		cout << "   b2_size : " << b2->getSize().first << " " << b2->getSize().second << endl;
    104		b1->setSize(400, 800);   // サイズの変更
    105		cout << "後 b1_size : " << b1->getSize().first << " " << b1->getSize().second << endl;
    106		cout << "   b2_size : " << b2->getSize().first << " " << b2->getSize().second << endl;
    107	
    108		return 0;
    109	}
    			
    015 行目~ 035 行目

      クラス Win に対する定義部分です.016 行目では,変数(メンバー変数) BGC を,string クラスのオブジェクトとして定義しています.string クラスは,文字列をサポートするクラスです.アクセス権が何も指定されていないため,この変数は,private 変数とみなされます.private 指定された変数は,そのクラスに定義された関数(メンバー関数( Win,getName,getBGC,getSize ),及び,そのクラスの変数へのアクセスを特別に許可された関数やクラス(フレンド関数フレンドクラス)だけから参照可能となります.ただし,静的メンバー関数 getName からは参照不可能です.

      017 行目において,protected 指定が行われていますので,異なる指定が行われるまで,これ以降に定義される変数や関数,この例においては,メンバー変数 size のアクセス権は protected になります.protected 指定された変数は,そのクラスに定義された関数(メンバー関数,この例では,Win,getName,getBGC,getSize ),そのクラスの変数へのアクセスを特別に許可された関数やクラス(フレンド関数フレンドクラス),及び,そのクラスを継承した派生クラスだけから参照可能となります.ただし,静的メンバー関数 getName からは参照不可能です.

      019 行目において,public 指定が行われていますので,異なる指定が行われるまで,これ以降に定義される変数や関数のアクセス権は public になります.public 指定された変数や関数は,すべてのクラス及びクラスの外部からの参照が可能になります.

      020 行目のメンバー変数 name に対しては,static 指定が行われています.クラス内の変数に対して static 指定を行うと,静的メンバー変数となります.通常,インスタンスを生成すると,クラス内の変数はインスタンス毎にその変数を記憶するための領域が確保されますが,静的メンバー変数の場合は,インスタンスを生成する前から,その変数を記憶する領域がクラスとは別に確保されます.従って,クラス外のグローバル領域において,変数を宣言し,その領域を確保しておく必要があります( 065 行目).また,関数に対して static 指定を行うと,静的メンバー関数となりますが,その関数から参照できる変数は静的メンバー変数だけとなります.

      静的メンバー変数や静的メンバー関数は,インスタンスを作成しなくても,
    	クラス名::静的メンバー変数名
    	クラス名::静的メンバー関数名
    				
    のような形で,変数の参照や関数の実行が可能になります( 070 行目~ 071 行目).また,インスタンスと関係なくその領域が確保されているため,クラス及びそのクラスを継承したすべてのクラスのインスタンスにおいて,その値は同じになります( 070 行目~ 071 行目,073 行目,及び,079 行目に対する出力結果).当然,いずれかにおいてその値を変更すれば,関連する他のクラス及びそのインスタンスにおいて値が変化します( 081 行目と 082 行目~ 084 行目に対する出力結果).

      021 行目では,メンバー変数 menu を,string クラスのオブジェクトを要素とする vector クラスのオブジェクトとして定義しています.vector クラスは,実行時における要素の追加や削除が可能である可変長の配列をサポートするクラスです.変数 menu に対するアクセス権は public ですので,077 行目に示すように,クラスの外部からも参照可能です.この点は,先に述べた変数 name に関しても同様です( 081 行目).

      023 行目~ 028 行目は,コンストラクタの定義です.コンストラクタはクラスのインスタンスを生成するとき( 072 行目),最初に呼ばれる関数であり,初期設定を行います.関数名は,クラス名と同じでなければならず,戻り値の型などを指定できません.ここでは,変数 size, BGC,及び,menu に対する初期値を設定しています.

      030 行目では,静的メンバー関数 getName を定義しています.先に述べたように,静的メンバー関数は,静的メンバー変数だけを参照できますので,この例においては,参照できる変数は name だけになります.また,対象とする変数が public ですので,あえてメンバー関数を定義せず,070 行目,073 行目のような形で,クラスの外部から直接変数を参照することも可能です.

      032 行目では,メンバー関数 getBGC に対する型宣言だけを行っています.その内容は,関数の外部,040 行目~ 043 行目に記述しています.このように,クラスの内部では,型の宣言だけを行い,その内容はクラスの外部に記述することも可能です.もちろん,他の関数のように,関数全体をクラス内部に記述することもできます.また,この関数が対象としている変数 BGC は private ですので,このような関数が存在しないと,変数 BGC をクラス外部から参照できなくなります.

      034 行目では,メンバー関数 getSize を定義しています.この関数が対象としている変数 size は protected ですので,このような関数が存在しないと,変数 size をクラス外部から参照できなくなります.

    048 行目~ 063 行目

      クラス Win (基底クラス)を継承するクラス App (派生クラス)に対する定義部分です.048 行目において public 指定を行っていますので,基底クラス Win の public 変数や関数はそのまま public に継承されます.この指定を行わないと,基底クラスにおける public 宣言されたすべての変数や関数は,private になってしまいます.静的メンバー変数 name の値は,クラス Win もクラス App も同じ領域を示していますので,079 行目に対応する出力結果からも明らかなように,クラス Win と同じになります.従って,081 行目に示すように,その値を変更すると,クラス Win に対する値も変化します( 082 行目~ 0084 行目).

      052 行目~ 054 行目は,App に対するコンストラクタの定義です.ここでは,変数 menu に要素を一つ追加しています.コンストラクタは継承されませんので,もし,基底クラスのコンストラクタに引き渡す引数が必要な場合は,ここで定義してやる必要があります.この例の場合,クラス App のコンストラクタは引数を必要としませんが,クラス Win のコンストラクタは 2 つの引数を必要としますので,80 行目のクラス App のインスタンスを生成する際に渡された引数を,「 : Win(s1, s2) 」の記述によって,クラス Win のコンストラクタに送っています.

      056 行目では,クラス App に新しく追加するメンバー関数 setSize を定義しています.この関数が対象としている変数 size は protected ですので,クラス Win を継承したクラス App に新しく追加したメンバー関数からも参照可能です.もちろん,この関数によって変化するのは,クラス App のインスタンスにおける size だけです( 089 行目~ 090 行目).

      058 行目は,メンバー変数 BGC の値を変更するために,クラス App にメンバー関数 setBGC を追加することを意図しています.しかし,058 行目,085 行目の変更だけでは,実現できません.なぜなら,メンバー変数 BGC が private であり,クラス Win のメンバー関数だけからしか参照できないからです(クラス App に追加された setBGC からは参照不可能).クラス App に対するインスタンスにおける BGC の値を変更できるようにするためには,058 行目,085 行目と共に,変数 BGC と 関数 getBGC の再定義( 049 行目のコメントを外す,060 行目のコメントを外し 061 行目をコメントに変更)が必要です.

      059 行目では,クラス Win の関数 getBGC を再定義しています.勿論,この例では,あえて再定義する必要はありません.再定義しなければ,基底クラス Win の getBGC をそのまま使用できます.060 行目の記述ではエラーになってしまいますので,061 行目のように基底クラス Win の getBGC を呼んでいます.

    093 行目~ 106 行目

      C++ においては,072 行目や 081 行目のような形でクラスのインスタンスを生成可能です.さらに,100 行目のように,new 演算子を使用してインスタンスを生成し,そのアドレスを変数に代入するといった形を使用することもできます.このとき,メンバー変数やメンバー関数に対する参照方法が,102 行目以降に示すように,ピリオド「 . 」ではなく「 -> 」になります.また,072 行目や 081 行目に示すインスタンス生成方法においては,093 行目のような代入(この場合は初期化ですが)を行った場合,a1 のすべての要素がコピーされて a2 に代入されます.従って,096 行目のように a1 の一部の値を変更しても a2 には影響しません.ただし,クラス内において new 演算子を使用している場合は,new 演算子によって得られたアドレスだけがコピーされ,アドレスが指しているデータはコピーされませんので注意してください(コピー元とコピー先で同じデータを指す).

      しかし,100 行目に示すインスタンス生成方法においては,101 行目のような代入を行うと,アドレス b1 が b2 にコピーされるわけですから,b1 と b2 は,同じ領域を指すことになり,b1 を介してその一部を変更すれば,b2 を介して見た内容も同じように変化します( 105 行目~ 106 行目).
      070 行目~ 106 行目内の出力文による出力結果です.ただし,コメント部分は対応する行番号であり,出力ではありません.
    Win_name : Window1   // 070 行目
    Win_name : Window1   // 071 行目
    w1_name : Window1   // 073 行目
    w1_BGC : white   // 074 行目
    w1_size : 100 200   // 076 行目
    w1_menu : file edit   // 077 行目
    
    App_name : Window1   // 079 行目
    Win_name : Window2   // 082 行目
    App_name : Window2   // 083 行目
    a1_name : Window2   // 084 行目
    a1_BGC : white   // 086 行目
    a1_size : 200 400   // 089 行目
    w1_size : 100 200   // 090 行目
    a1_menu : file edit other   // 091 行目
    
    前 a1_size : 200 400   // 094 行目
       a2_size : 200 400   // 095 行目
    後 a1_size : 300 600   // 097 行目
       a2_size : 200 400   // 098 行目
    前 b1_size : 100 200   // 102 行目
       b2_size : 100 200   // 103 行目
    後 b1_size : 400 800   // 105 行目
       b2_size : 400 800   // 106 行目
    			

  2. Java

    01	/******************************/
    02	/* クラスに対するプログラム例 */
    03	/*      coded by Y.Suganuma   */
    04	/******************************/
    05	import java.io.*;
    06	import java.util.*;
    07	
    08	public class Test {
    09		public static void main(String args[]) throws IOException
    10		{
    11				// クラス Win
    12			System.out.printf("Win_name : %s\n", Win.name);   // 名前,static 指定のため可
    13			System.out.printf("Win_name : %s\n", Win.getName());   // 名前,static 変数だけを参照可
    14			Win w1 = new Win("file", "edit");
    15			System.out.printf("w1_name : %s\n", w1.name);   // 名前
    16			System.out.printf("w1_BGC : %s\n", w1.getBGC());   // 背景色
    17			int s[] = w1.getSize();   // サイズの取得
    18			System.out.printf("w1_size : %d %d\n", s[0], s[1]);
    19			System.out.printf("w1_menu : %s %s\n", w1.menu.get(0), w1.menu.get(1));   // メニュー
    20				// クラス App(クラス Win を継承)
    21			System.out.printf("\nApp_name : %s\n", App.name);   // 名前,App.getName() でも可
    22			App a1 = new App("file", "edit");
    23			System.out.printf("a1_name : %s\n", a1.name);   // 名前
    24	//		a1.setBGC("red");   // スーパークラスの private 変数にアクセスできない
    25			System.out.printf("a1_BGC : %s\n", a1.getBGC());   // 背景色
    26			a1.setSize(200, 400);   // サイズの変更
    27			s = a1.getSize();
    28			System.out.printf("a1_size : %d %d\n", s[0], s[1]);
    29			System.out.printf("w1_size : %d %d\n", w1.getSize()[0], w1.getSize()[1]);
    30			System.out.printf("a1_menu : %s %s %s\n", a1.menu.get(0), a1.menu.get(1), a1.menu.get(2));   // メニュー
    31				// 代入
    32			App a2 = a1;
    33			System.out.printf("\n前 a1_size : %d %d\n", a1.getSize()[0],a1.getSize()[1]);
    34			System.out.printf("   a2_size : %d %d\n", a2.getSize()[0],a2.getSize()[1]);
    35			a1.setSize(300, 600);   // サイズの変更
    36			System.out.printf("後 a1_size : %d %d\n", a1.getSize()[0],a1.getSize()[1]);
    37			System.out.printf("   a2_size : %d %d\n", a2.getSize()[0],a2.getSize()[1]);
    38		}
    39	}
    40	
    41	/**************/
    42	/* クラス Win */
    43	/**************/
    44	class Win {
    45		final static String name = "Window1";   // 名前
    46		private String BGC = "white";   // 背景色
    47		protected int size[] = {100, 200};   // サイズ(縦と横)
    48		ArrayList <String> menu = new ArrayList <String> ();   // メニュー
    49				// コンストラクタ
    50		Win (String s1, String s2) {
    51			menu.add(s1);
    52			menu.add(s2);
    53		}
    54				// 名前の取得
    55		static String getName() { return name; }
    56				// 背景色の取得
    57		String getBGC() { return BGC; }
    58				// サイズの取得
    59		int[] getSize() { return size; }
    60	}
    61	
    62	/**************/
    63	/* クラス App */
    64	/**************/
    65	class App extends Win {   // クラス Win を継承
    66	//	private String BGC;   // 背景色
    67				// コンストラクタ
    68		App(String s1, String s2) {
    69			super(s1, s2);
    70			menu.add("other");
    71		}
    72				// サイズの変更
    73		void setSize(int row, int col) { size[0] = row; size[1] = col; }
    74				// 背景色の変更(スーパークラスの private 変数にアクセスできない)
    75	//	void setBGC(String col) { BGC = col; }
    76	//	String getBGC() { return BGC; }
    77	}
    			
    44 行目~ 60 行目

      クラス Win に対する定義部分です.45 行目において,変数( C++ におけるメンバー変数に相当) name を,String クラスのオブジェクトとして定義しています.String クラスは,文字列をサポートするクラスです.変数 name に対しては,static 指定が行われています.クラス内の変数に対して static 指定を行うと,静的メンバー変数となります.また,関数( Java においては,通常,メソッドと呼ぶ)に対して static 指定を行うと,静的メンバー関数となりますが,その関数から参照できる変数は静的メンバー変数だけとなります.

      静的メンバー変数や静的メンバー関数は,インスタンスを作成しなくても,
    	クラス名.静的メンバー変数名
    	クラス名.静的メンバー関数名
    				
    のような形で,変数の参照や関数の実行が可能になります( 12 行目~ 13 行目).また,通常,インスタンスを生成すると,クラス内の変数はインスタンス毎にその値を変更できますが,静的メンバー変数の場合は,異なるインスタンスであっても,クラスが同じ,または,そのクラスを継承したクラスであれば同じ値となります( 12 行目~ 13 行目,15 行目,21 行目,及び,23 行目に対する出力結果).この例では,name に対して final 指定がされているため,その値を変更できませんが,変更可能な場合,いずれかにおいてその値を変更すれば,関連する他のクラス及びそのインスタンスにおいて値が変化します.

      46 行目では,メンバー変数 BGC を String クラスのオブジェクトとして定義し,アクセス権として private を指定しています.private 指定された変数は,そのクラスに定義された関数( C++ におけるメンバー関数に相当,この例では,Win,getName,getBGC,getSize )だけから参照可能となります.ただし,静的メンバー関数 getName からは参照不可能です.

      47 行目では,メンバー変数 size を,整数を要素とする配列として定義し,protected 指定しています.protected 指定された変数は,そのクラスに定義された関数( C++ におけるメンバー関数に相当,この例では,Win,getName,getBGC,getSize ),及び,そのクラスを継承したサブクラスだけから参照可能となります.ただし,静的メンバー関数 getName からは参照不可能です.

      48 行目では,メンバー変数 menu を,String クラスのオブジェクトを要素とする ArrayList クラスのオブジェクトとして定義しています.ArrayList クラスは,実行時における要素の追加や削除が可能である可変長の配列をサポートするクラスです.この変数に対しては,publicprivateprotected などの指定が行われていません.これらのいずれの指定も行わないと,同じクラス内及び同じパッケージ内のクラスから参照可能になります( 19 行目,同じパッケージ内のクラス Test からの参照).なお,public 指定を行うと,異なるパッケージからの参照も可能になります.

      50 行目~ 53 行目は,コンストラクタの定義です.コンストラクタはクラスのインスタンスを生成するとき( 14 行目),最初に呼ばれる関数であり,初期設定を行います.関数名は,クラス名と同じでなければならず,戻り値の型などを指定できません.ここでは,変数 menu に対する初期値を設定しています.

      55 行目では,静的メンバー関数 getName を定義しています.先に述べたように,静的メンバー関数は,静的メンバー変数だけを参照できますので,この例においては,参照できる変数は name だけになります.また,対象とする変数のアクセス権が指定されていませんので,あえてメンバー関数を定義せず,12 行目,15 行目のような形で直接参照することも可能です.

      57 行目では,メンバー関数 getBGC を定義しています.この関数が対象としている変数 BGC は private ですので,このような関数が存在しないと,変数 BGC を同じパッケージ内の他のクラス(ここでは,クラス Test )からも参照できなくなります.

      59 行目では,メンバー関数 getSize を定義しています.この関数が対象としている変数 size は protected ですので,このような関数が存在しないと,変数 size を同じパッケージ内の他のクラス(ここでは,クラス Test )からも参照できなくなります.

    65 行目~ 77 行目

      クラス Win (スーパークラス)を継承するクラス App (サブクラス)に対する定義部分です.静的メンバー変数 name の値は,21 行目,23 行目に対応する出力結果からも明らかなように,クラス Win と同じになります.

      68 行目~ 71 行目は,App に対するコンストラクタの定義です.ここでは,変数 menu に要素を一つ追加しています.コンストラクタは継承されませんので,スーパークラスのコンストラクタの呼び出しが必要な場合は,この位置において,super を使用して,明示的に呼び出す必要があります.この例では,クラス App のコンストラクターは引数を必要としませんが,クラス Win のコンストラクタは 2 つの引数を必要とします.そのため,クラス App のインスタンスを生成する際にも 2 つの引数が必要となり( 22 行目),その引数を使用し,69 行目においてクラス Win のコンストラクタを呼んでいます.

      73 行目では,クラス App に新しく追加するメンバー関数 setSize を定義しています.この関数が対象としている変数 size は protected ですので,クラス Win を継承したクラス App に新しく追加したメンバー関数からも参照可能です.もちろん,この関数によって変化するのは,クラス App のインスタンスにおける size だけです( 28 行目~ 29 行目).

      75 行目は,メンバー変数 BGC の値を変更するために,クラス App にメンバー関数 setBGC を追加することを意図しています.しかし,24 行目,75 行目の変更だけでは,実現できません.なぜなら,メンバー変数 BGC が private であり,クラス Win のメンバー関数だけからしか参照できないからです(クラス App に追加された setBGC からは参照不可能).クラス App に対するインスタンスにおける BGC の値を変更できるようにするためには,24 行目,75 行目と共に,変数 BGC と 関数 getBGC の再定義( 66 行目と 76 行目)が必要です.

    32 行目~ 37 行目

      Java におけるクラスのインスタンス生成方法( 14 行目,22 行目)は,C++ における new 演算子を使用した方法( C++ に対するプログラム例の 100 行目)に非常に似ています.実際,変数 w1 や a1 には,インスタンスのアドレスが記憶されているとみることができます.従って,32 行目のような代入を行った場合,アドレス a1 が a2 にコピーされるわけですから,a1 と a2 は,同じ領域を指すことになり,a1 を介してその一部を変更すれば,a2 を介して見た内容も同じように変化します( 36 行目~ 37 行目).
      12 行目~ 37 行目内の出力文による出力結果です.ただし,コメント部分は対応する行番号であり,出力ではありません.
    Win_name : Window1   // 12 行目
    Win_name : Window1   // 13 行目
    w1_name : Window1   // 15 行目
    w1_BGC : white   // 16 行目
    w1_size : 100 200   // 18 行目
    w1_menu : file edit   // 19 行目
    
    App_name : Window1   // 21 行目
    a1_name : Window1   // 23 行目
    a1_BGC : white   // 25 行目
    a1_size : 200 400   // 28 行目
    w1_size : 100 200   // 29 行目
    a1_menu : file edit other   // 30 行目
    
    前 a1_size : 200 400   // 33 行目
       a2_size : 200 400   // 34 行目
    後 a1_size : 300 600   // 36 行目
       a2_size : 300 600   // 37 行目
    			

  3. JavaScript

      JavaScript には,クラスの機能がありませんので,似た機能であるオブジェクトについて説明します.ここをクリックすれば,ブラウザ上で実行することができます.また,ページのソースを表示すれば,下に示した JavaScript のソースプログラムも表示可能です.

    01	<!DOCTYPE HTML>
    02	<HTML>
    03	<HEAD>
    04		<TITLE>クラス</TITLE>
    05		<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=utf-8">
    06		<SCRIPT TYPE="text/javascript">
    07			/******************************/
    08			/* クラスに対するプログラム例 */
    09			/*      coded by Y.Suganuma   */
    10			/******************************/
    11			function run() {
    12				let w1  = new Win();
    13				let str = "Win_name : " + w1.name + "\n";   // 名前
    14				str    += "w1_BGC : " + w1.getBGC(w1) + "\n";   // 背景色
    15				let s   = w1.getSize(w1);   // サイズの取得
    16				str    += "w1_size : " + s[0] + " " + s[1] + "\n";
    17				str    += "w1_menu : " + w1.menu[0] + " " + w1.menu[1] + "\n";   // メニュー
    18				let w2  = w1;
    19				str    += "前 w1_BGC : " + w1.BGC + "\n";
    20				str    += "   w2_BGC : " + w2.BGC + "\n";
    21				w1.BGC  = "red";
    22				str    += "後 w1_BGC : " + w1.BGC + "\n";
    23				str    += "   w2_BGC : " + w2.BGC + "\n";
    24					// 結果の設定
    25				document.getElementById("tx").value = str;
    26			}
    27	
    28			/********************/
    29			/* オブジェクト Win */
    30			/********************/
    31			function Win()
    32			{
    33				this.BGC  = "white";   // 背景色
    34				this.name = "Window";   // 名前
    35				this.size = new Array(100, 200);   // サイズ(縦と横)
    36				this.menu = new Array("file", "edit");   // メニュー
    37			}
    38	
    39			Win.prototype.getBGC = function(w) { return w.BGC; }
    40			Win.prototype.getSize = function(w) { return w.size; }
    41		</SCRIPT>
    42	</HEAD>
    43	<BODY  STYLE="font-size:130%">
    44		<P STYLE="text-align:center">
    45			<INPUT TYPE="button" VALUE="OK" onClick="run()" STYLE="font-size:90%"><BR><BR>
    46			<TEXTAREA TYPE="text" ID="tx" COLS="25" ROWS="5" STYLE="font-size: 100%"></TEXTAREA>
    47		</P>
    48	</BODY>
    49	</HTML>
    			
    31 行目~ 37 行目

      オブジェクト Win に対する定義部分です.12 行目のように,新しいオブジェクト Win を生成すると,最初に呼ばれる関数です.そのような意味から,クラスにおけるコンストラクタに似ています.ここでは,4 つの変数 BGC,name,size,menu の初期設定をしています.これらの変数は,クラスにおける public 指定されたメンバー変数に相当します.this というキーワードを忘れないでください.

    39 行目

      関数 getBGC を定義しています.クラスにおけるメンバー関数に相当します.このような関数を定義せず,19 行目~ 20 行目,22 行目~ 23 行目のような形で,変数 BGC を直接参照することも可能です.

    40 行目

      関数 getSize を定義しています.変数 size に関しても,直接参照することも可能です.

    18 行目~ 23 行目

      JavaScript におけるオブジェクト生成方法( 12 行目)は,C++ における new 演算子を使用した方法( C++ に対するプログラム例の 100 行目)に非常に似ています.実際,変数 w1 には,オブジェクトのアドレスが記憶されているとみることができます.従って,18 行目のような代入を行った場合,アドレス w1 が w2 にコピーされるわけですから,w1 と w2 は,同じ領域を指すことになり,w1 を介してその一部を変更すれば,w2 を介して見た内容も同じように変化します( 22 行目~ 23 行目).
      12 行目~ 23 行目内の文による出力結果です.ただし,コメント部分は対応する行番号であり,出力ではありません.
    Win_name : Window   // 13 行目
    w1_BGC : white   // 14 行目
    w1_size : 100 200   // 16 行目
    w1_menu : file edit   // 17 行目
    前 w1_BGC : white   // 19 行目
       w2_BGC : white   // 20 行目
    後 w1_BGC : red   // 22 行目
       w2_BGC : red   // 23 行目
    			

  4. PHP

    01	<?php
    02		/****************************/
    03		/* 関数に対するプログラム例 */
    04		/*      coded by Y.Suganuma */
    05		/****************************/
    06				// クラス Win
    07		printf("Win_name : %s\n", Win::$name);   // 名前,static 指定のため可
    08		printf("Win_name : %s\n", Win::getName());   // 名前,static 変数だけを参照可
    09		$w1 = new Win("file", "edit");
    10	//	printf("w1_name : %s\n", $w1->name);   // 許されない
    11		printf("w1_BGC : %s\n", $w1->getBGC());   // 背景色
    12		$s = $w1->getSize();   // サイズの取得
    13		printf("w1_size : %d %d\n", $s[0], $s[1]);
    14		printf("w1_menu : %s %s\n", $w1->menu[0], $w1->menu[1]);   // メニュー
    15				// クラス App(クラス Win を継承)
    16		printf("\nApp_name : %s\n", App::$name);   // 名前,Win クラスと同じ
    17		$a1 = new App("file", "edit");
    18		printf("App_name : %s\n", App::$name);   // 新しい名前
    19		printf("Win_name : %s\n", Win::$name);   // 新しい名前
    20		$a1->setBGC("red");   // ここで,App の $BGC が定義される
    21		printf("a1_BGC : %s\n", $a1->BGC);   // 背景色
    22		printf("a1_BGC : %s\n", $a1->getBGC());   // 背景色
    23		printf("w1_BGC : %s\n", $w1->getBGC());   // 背景色
    24		$a1->setSize(200, 400);   // サイズの変更
    25		$s = $a1->getSize();   // サイズの取得
    26		printf("a1_size : %d %d\n", $s[0], $s[1]);
    27		printf("w1_size : %d %d\n", $w1->getSize()[0], $w1->getSize()[1]);
    28		printf("a1_menu : %s %s %s\n", $a1->menu[0], $a1->menu[1], $a1->menu[2]);   // メニュー
    29				// 代入
    30		$a2 = $a1;
    31		printf("\n前 a1_size : %d %d\n", $a1->getSize()[0], $a1->getSize()[1]);
    32		printf("   a2_size : %d %d\n", $a2->getSize()[0], $a2->getSize()[1]);
    33		$a1->setSize(300, 600);   // サイズの変更
    34		printf("後 a1_size : %d %d\n", $a1->getSize()[0], $a1->getSize()[1]);
    35		printf("   a2_size : %d %d\n", $a2->getSize()[0], $a2->getSize()[1]);
    36	
    37		/**************/
    38		/* クラス Win */
    39		/**************/
    40		class Win {
    41			static $name    = "window1";
    42			private $BGC    = "white";
    43			protected $size = array(100, 200);
    44			public $menu    = array();
    45				// コンストラクタ
    46			function Win($s1, $s2) {
    47				$this->menu[0] = $s1;
    48				$this->menu[1] = $s2;
    49			}
    50				// 名前の取得
    51			static function getName() { return self::$name; }
    52				// 背景色の取得
    53			function getBGC() { return $this->BGC; }
    54				// サイズの取得
    55			function getSize() { return $this->size; }
    56		}
    57	
    58		/**************/
    59		/* クラス App */
    60		/**************/
    61		class App extends Win {   // クラス Win を継承
    62	//		private $BGC;
    63				// コンストラクタ
    64			function App($s1, $s2) {
    65				self::$name    = "window2";   // インスタンス化できないため,$this の代わりに self を使用
    66				parent::Win($s1, $s2);
    67				$this->menu[2] = "other";
    68			}
    69				// サイズの変更
    70			function setSize($row, $col) { $this->size[0] = $row; $this->size[1] = $col; }
    71				// 背景色の変更
    72			function setBGC($col) { $this->BGC = $col; }   //   $BGC の定義も行われる
    73	//		function getBGC() { return $this->BGC; }   // 記述しないと親の BGC 参照
    74		}
    75	?>
    			
    40 行目~ 56 行目

      クラス Win に対する定義部分です.41 行目において,変数( C++ におけるメンバー変数に相当) $name を,文字列として定義しています.変数 $name に対しては,static 指定が行われています.クラス内の変数に対して static 指定を行うと,静的メンバー変数となります.また,関数に対して static 指定を行うと,静的メンバー変数となりますが,その関数から参照できる変数は静的メンバー変数だけとなります.

      静的メンバー変数や静的メンバー関数は,インスタンスを作成しなくても,
    	クラス名::静的メンバー変数名
    	クラス名::静的メンバー関数名
    				
    のような形で,変数の参照や関数の実行が可能になります( 07 行目~ 08 行目).また,通常,インスタンスを生成すると,クラス内の変数はインスタンス毎にその値を変更できますが,静的メンバー変数の場合はインスタンス化できず,07 行目~ 08 行目の参照方法しか許されません( 10 行目).また,いずれかにおいてその値が変更された場合,継承関係にあるクラスにおける値も変化します( 18 行目~ 19 行目).

      42 行目では,メンバー変数 $BGC を文字列として定義し,アクセス権として private を指定しています.private 指定された変数は,そのクラスに定義された関数( C++ におけるメンバー関数に相当,この例では,getName,getBGC,getSize )だけから参照可能となります.ただし,静的メンバー関数 getName からは参照不可能です.また,private 指定された変数は,そのクラスを継承した派生クラスには継承されません.

      43 行目では,メンバー変数 $size を,整数を要素とする配列として定義し,protected 指定しています.protected 指定された変数は,そのクラスに定義された関数( C++ におけるメンバー関数に相当,この例では,getName,getBGC,getSize ),及び,そのクラスを継承した派生クラスだけから参照可能となります.ただし,静的メンバー関数 getName からは参照不可能です.

      44 行目では,メンバー変数 $menu を,文字列を要素とする配列として定義し,public 指定しています.public 指定された変数は,すべてのクラス,及び,クラスの外部からも参照可能になります( 14 行目).

      46 行目~ 49 行目は,コンストラクタです.受け取った 2 つの引数によって,$menu の初期設定を行っています.コンストラクタはクラスのインスタンスを生成するとき( 09 行目),最初に呼ばれる関数であり,初期設定を行います.関数名は,クラス名と同じでなければなりません.

      51 行目では,静的メンバー関数 getName を定義しています.先に述べたように,静的メンバー関数は,静的メンバー変数だけを参照できますので,この例においては,参照できる変数は $name だけになります.この例においては,07 行目のような形で $name を参照できますので,必ずしもこの関数を要とはしません.

      53 行目では,メンバー関数 getBGC を定義しています.この関数が対象としている変数 $BGC は private ですので,このような関数が存在しないと,変数 $BGC を他のクラスやクラス外部から参照できなくなります.

      55 行目では,メンバー関数 getSize を定義しています.この関数が対象としている変数 $size は protected ですので,このような関数が存在しないと,変数 $size を他のクラスやクラス外部から参照できなくなります.

    61 行目~ 74 行目

      クラス Win (基底クラス)を継承するクラス App (派生クラス)に対する定義部分です.静的メンバー変数 $name の値は,16 行目に対応する出力結果からも明らかなように,クラス Win と同じになります.

      64 行目~ 68 行目は,App に対するコンストラクタの定義です.ここでは,変数 $name の値を変更し(その結果は,18 行目,19 行目),かつ,変数 $menu に要素を一つ追加しています.なお,通常のメンバー変数を参照する場合は this. を使用しますが( 67 行目),静的メンバー変数の場合は self:: を使用する点に注意してください.

      コンストラクタは継承されませんので,基底クラスのコンストラクタの呼び出しが必要な場合は,この位置において,parent を使用して明示的に呼び出す必要があります.この例の場合,クラス App のコンストラクタは引数を必要としませんが,基底クラス Win は 2 つの引数を必要としますので,クラス App のインスタンスを定義する場合に 2 つの引数を必要とします( 17 行目).ここでは,渡された引数を使用して,66 行目において基底クラスのコンストラクタを呼んでいます.

      70 行目では,クラス App に新しく追加するメンバー関数 setSize を定義しています.この関数が対象としている変数 $size は protected ですので,クラス Win を継承したクラス App に新しく追加したメンバー関数からも参照可能です.もちろん,この関数によって変化するのは,クラス App のインスタンスだけです( 26 行目~ 27 行目).

      72 行目は,メンバー変数 $BGC の値を変更するために,メンバー関数 setBGC を定義しています.クラス Win において private 指定された変数 $BGC は継承されませんので,この関数内でクラス App のメンバー変数 $BGC を定義することになります.しかし,この形で定義すると,変数 $BGC は public 指定された変数となり,クラスの外部から参照可能になります( 21 行目).private 指定したい場合は,62 行目を追加する必要があります.

      73 行目では,メンバー変数 $BGC の値を取得するために,メンバー関数 getBGC を定義しようとしています.ここで getBGC を定義しなくても,クラス Win から継承されるため,22 行目の実行においてエラーにはなりませんが,取得される値は,基底クラス Win の $BGC の値となってしまいます.この点を避けるためには,ここで行おうとしているように,メンバー関数 getBGC を再定義する必要があります.

    30 行目~ 35 行目

      PHP におけるクラスのインスタンス生成方法( 09 行目,17 行目)は,C++ における new 演算子を使用した方法( C++ に対するプログラム例の 100 行目)に非常に似ています.実際,変数 $w1 や $a1 には,インスタンスのアドレスが記憶されているとみることができます.従って,30 行目のような代入を行った場合,アドレス $a1 が $a2 にコピーされるわけですから,$a1 と $a2 は,同じ領域を指すことになり,$a1 を介してその一部を変更すれば,$a2 を介して見た内容も同じように変化します( 34 行目~ 35 行目).
      07 行目~ 35 行目内の出力文による出力結果です.ただし,コメント部分は対応する行番号であり,出力ではありません.
    Win_name : window1   // 07 行目
    Win_name : window1   // 08 行目
    w1_BGC : white   // 11 行目
    w1_size : 100 200   // 13 行目
    w1_menu : file edit   // 14 行目
    
    App_name : window1   // 16 行目
    App_name : window2   // 18 行目
    Win_name : window2   // 19 行目
    a1_BGC : red   // 21 行目
    a1_BGC : white   // 22 行目
    w1_BGC : white   // 23 行目
    a1_size : 200 400   // 26 行目
    w1_size : 100 200   // 27 行目
    a1_menu : file edit other   // 28 行目
    
    前 a1_size : 200 400   // 31 行目
       a2_size : 200 400   // 32 行目
    後 a1_size : 300 600   // 34 行目
       a2_size : 300 600   // 35 行目
    			

  5. Ruby

    01	##############################
    02	# クラスに対するプログラム例 #
    03	#      coded by Y.Suganuma   #
    04	##############################
    05	
    06	##############
    07	# クラス Win #
    08	##############
    09	class Win
    10		Name    = "Window";   # 名前
    11		@@_name = "other";   # クラス変数
    12				# 初期設定(コンストラクタ)
    13		def initialize(s1, s2)
    14			@_BGC  = "white";
    15			@_size = [100, 200];
    16			@_menu = [s1, s2];
    17		end
    18				# 背景色の取得
    19		def getBGC()
    20			return @_BGC;
    21		end
    22				# サイズの取得
    23		def getSize()
    24			return @_size;
    25		end
    26				# インスタンス変数の読み込み許可
    27		attr("_menu");
    28	#	attr_accessor("_menu");   # インスタンス変数の読み込み,書き込み許可
    29	end
    30	
    31	##############
    32	# クラス App #
    33	##############
    34	class App < Win   # クラス Win を継承
    35				# 初期設定(コンストラクタ)
    36		def initialize(s1, s2)
    37			super(s1, s2);   # 記述しないとオーバーライドされる
    38			@_menu[2] = @@_name;
    39		end
    40				# サイズの変更
    41		def setSize(row, col)
    42			@_size[0] = row;
    43			@_size[1] = col;
    44		end
    45				# 背景色の変更
    46		def setBGC(c)
    47			@_BGC = c;
    48		end
    49	end
    50	
    51				# クラス Win
    52	printf("Win_name : %s\n", Win::Name);   # 名前
    53	w1 = Win.new("file", "edit");
    54	#printf("Win_name : %s\n", w1.Name);   # 許されない
    55	printf("w1_BGC : %s\n", w1.getBGC());   # 背景色
    56	s = w1.getSize();   # サイズの取得
    57	printf("w1_size : %d %d\n", s[0], s[1]);
    58	printf("w1_menu : %s %s\n", w1._menu[0], w1._menu[1]);   # メニュー
    59				# クラス App(クラス Win を継承)
    60	printf("\nApp_name : %s\n", App::Name);   # 名前,Win クラスと同じ
    61	a1 = App.new("file", "edit");
    62	a1.setBGC("red");   # 色の変更
    63	printf("a1_BGC : %s\n", a1.getBGC());   # 背景色(a1)
    64	printf("w1_BGC : %s\n", w1.getBGC());   # 背景色(w1)
    65	a1.setSize(200, 400);   # サイズの変更
    66	s = a1.getSize();   # サイズの取得
    67	printf("a1_size : %d %d\n", s[0], s[1]);
    68	printf("w1_size : %d %d\n", w1.getSize()[0], w1.getSize()[1]);
    69	printf("a1_menu : %s %s %s\n", a1._menu[0], a1._menu[1], a1._menu[2]);   # メニュー
    70				# 代入
    71	a2 = a1;
    72	printf("\n前 a1_size : %d %d\n", a1.getSize()[0], a1.getSize()[1]);
    73	printf("   a2_size : %d %d\n", a2.getSize()[0], a2.getSize()[1]);
    74	a1.setSize(300, 600);   # サイズの変更
    75	printf("後 a1_size : %d %d\n", a1.getSize()[0], a1.getSize()[1]);
    76	printf("   a2_size : %d %d\n", a2.getSize()[0], a2.getSize()[1]);
    			
    09 行目~ 29 行目

      クラス Win に対する定義部分です.10 行目において,定数 Name を文字列として定義しています.アルファベット大文字( [ A - Z ] )で始まる識別子は定数です.定数の定義は代入によって行われますが,関数( Ruby においては,通常,メソッドと呼ぶ)の中では定義できません.定数は,その定数が定義されたクラス/モジュール定義の中(関数本体やネストしたクラス/モジュール定義中を含みます),クラスを継承しているクラス,モジュールをインクルードしているクラス,または,モジュールから参照することができます.定数を,クラス外から参照するためには,52 行目,60 行目に示すように,
    	クラス名::定数
    				
    のような形で行います.このような点から,C++ における静的メンバー変数と似ています.

      11 行目では,クラス変数 @@_name を文字列として定義しています.@@ で始まる変数はクラス変数と呼びます.クラス変数は,クラス定義の中で定義され,クラス,及び,そのクラスを継承しているクラスから参照できます.このような点から,クラス変数は,クラスやそのクラスを継承しているクラスで共有されるグローバル変数であるとみなすことができます.

      13 行目~ 17 行目では,関数 initialize を定義しています.initialize は,初期設定を行う関数であり,C++ におけるコンストラクタに似ています.ここでは,3 つのインスタンス変数 @_BGC,@_size,@_menu に対する初期設定を行っています.@ で始まる変数は,インスタンス変数と呼ばれ,特定のオブジェクトに所属しています.インスタンス変数はそのクラスまたはクラスを継承しているクラスの関数から参照できます.インスタンス変数は,クラスから生成されたインスタンス(オブジェクト)毎に別の値を持つことができるため,各オブジェクトの状態を表すためなどに使用されます.このように,インスタンス変数は,C/C++ における protected 指定されたメンバー変数と似た働きをします.

      19 行目~ 21 行目では,関数 getBGC を定義しています.この関数が対象としている変数 @_BGC はインスタンス変数ですので,このような関数が存在しないと,変数 @_BGC をクラス外部から参照できなくなります( 55 行目).関数 getBGC は,C/C++ におけるメンバー関数と似た働きをします.

      23 行目~ 25 行目では,関数 getSize を定義しています.この関数が対象としている変数 @_size はインスタンス変数ですので,このような関数が存在しないと,変数 @_size をクラス外部から参照できなくなります( 56 行目).関数 getSize は,C/C++ におけるメンバー関数と似た働きをします.

      上で述べたように,一般に,@ で始まるインスタント変数は,クラスの外から参照することは不可能です.27 行目では,Module クラスの関数 attr を使用して,クラスの外からインスタント変数 @_menu の読み込みを可能にしています( 58 行目).書き込みも可能にするには,28 行目に示すように,attr_accessor を使用します.

      Ruby では,組み込み変数として意味の無い記号に様々な意味を与えたり,クラスにおいても,上で述べたように,大文字で始まる変数,@@ で始まる変数,@ で始まる変数など,ここでも,意味の無い記号に対して特別な意味を与えています.Ruby の世界から絶対に出ないような人にとっては良いのかもしれませんが,Ruby に縁の無い人にとっては理解しがたい世界です.このような仕様を設定したことに疑問を感じざるを得ません.

    34 行目~ 49 行目

      クラス Win (スーパークラス)を継承するクラス App (サブクラス)に対する定義部分です.定数 Name の値は,60 行目に対応する出力結果からも明らかなように,クラス Win と同じになります.

      36 行目~ 39 行目は,App に対する関数 initialize の再定義です.37 行目を記述しないと,Win クラスの initialize をオーバーライドするだけになりますので,Win クラスの initialize で定義した情報はすべて失われます.super は,Win クラスの initialize を実行するために必要となります.ここでは,それに加え,変数 @_menu に要素を一つ追加しています(クラス変数 @@_name の利用).

      41 行目~ 44 行目では,クラス App に新しく追加する関数 setSize を定義しています.もちろん,この関数によって変化するのは,クラス App のインスタンスの @_size だけです( 67 行目~ 68 行目).

      46 行目~ 48 行目では,クラス App に新しく追加する関数 setBGC を定義しています.もちろん,この関数によって変化するのは,クラス App のインスタンスの @_BGC だけです( 63 行目~ 64 行目).

    71 行目~ 76 行目

      Ruby におけるクラスのインスタンス生成方法( 53 行目,61 行目)は,C++ における new 演算子を使用した方法( C++ に対するプログラム例の 100 行目)に非常に似ています.実際,変数 w1 や a1 には,インスタンスのアドレスが記憶されているとみることができます.従って,71 行目のような代入を行った場合,アドレス a1 が a2 にコピーされるわけですから,a1 と a2 は,同じ領域を指すことになり,a1 を介してその一部を変更すれば,a2 を介して見た内容も同じように変化します( 75 行目~ 76 行目).
      52 行目~ 76 行目内の出力文による出力結果です.ただし,コメント部分は対応する行番号であり,出力ではありません.
    Win_name : Window   # 52 行目
    w1_BGC : white   # 55 行目
    w1_size : 100 200   # 57 行目
    w1_menu : file edit   # 58 行目
    
    App_name : Window   # 60 行目
    a1_BGC : red   # 63 行目
    w1_BGC : white   # 64 行目
    a1_size : 200 400   # 67 行目
    w1_size : 100 200   # 68 行目
    a1_menu : file edit other   # 69 行目
    
    前 a1_size : 200 400   # 72 行目
       a2_size : 200 400   # 73 行目
    後 a1_size : 300 600   # 75 行目
       a2_size : 300 600   # 76 行目
    			

  6. Python

    01	# -*- coding: UTF-8 -*-
    02	
    03	##############################
    04	# クラスに対するプログラム例 #
    05	#      coded by Y.Suganuma   #
    06	##############################
    07	
    08	##############
    09	# クラス Win #
    10	##############
    11	class Win :
    12		name = "Window1";   # 名前
    13				# 初期化(コンストラクタ)
    14		def __init__(self, s1, s2) :
    15			self.BGC  = "white"
    16			self.size = [100, 200]
    17			self.menu = [s1, s2]
    18				# 背景色の取得
    19		def getBGC(self) : return self.BGC
    20				# サイズの取得
    21		def getSize(self) : return self.size
    22				# 名前の取得(クラスメソッド)
    23		@classmethod
    24		def getName_c(cls) :
    25			return cls.name
    26				# 名前の取得(スタティックメソッド)
    27		@staticmethod
    28		def getName_s() :
    29			return Win.name
    30	
    31	##############
    32	# クラス App #
    33	##############
    34	class App(Win) :   # クラス Win を継承
    35				# 初期化(コンストラクタ)
    36		def __init__(self, s1, s2) :
    37			Win.__init__(self, s1, s2)
    38			(self.menu).append("other")
    39				# サイズの変更
    40		def setSize(self, row, col) :
    41			self.size[0] = row
    42			self.size[1] = col
    43				# 背景色の変更
    44		def setBGC(self, col) : self.BGC = col
    45	
    46				# クラス Win
    47	print("Win_name :", Win.name)   # 名前
    48	w1 = Win("file", "edit")
    49	print("w1_name :", w1.name)   # 名前
    50	print("w1_name(c) :", w1.getName_c())   # 名前(クラスメソッド)
    51	print("w1_name(s) :", w1.getName_s())   # 名前(スタティックメソッド)
    52	print("w1_BGC :", w1.getBGC())   # 背景色,print(w1.BGC) でも可
    53	s = w1.getSize()   # サイズの取得,s = w1.size でも可
    54	print("w1_size :", s[0], s[1])
    55	print("w1_menu :", w1.menu[0], w1.menu[1])   # メニュー
    56				# クラス App
    57	print("\nApp_name :", App.name)   # 名前(App)
    58	print("Win_name :", Win.name)   # 名前(Win)
    59	a1       = App("file", "edit")
    60	App.name = "Window2"
    61	a1.name  = "Window3"
    62	print("App_name :", App.name)   # 名前(App)
    63	print("Win_name :", Win.name)   # 名前(Win)
    64	print("a1_name :", a1.name)   # 名前
    65	print("a1_name(c) :", a1.getName_c())   # 名前(クラスメソッド)
    66	print("a1_name(s) :", a1.getName_s())   # 名前(スタティックメソッド)
    67	a1.setBGC("red");
    68	print("a1_BGC :", a1.getBGC())   # 背景色,print(a1.BGC) でも可
    69	print("w1_BGC :", w1.getBGC())   # 背景色,print(w1.BGC) でも可
    70	a1.setSize(200, 400)   # サイズの変更
    71	s = a1.getSize()   # サイズの取得,s = a1.size でも可
    72	print("a1_size :", s[0], s[1])
    73	print("w1_size :", w1.getSize()[0], w1.getSize()[1])
    74	print("a1_menu :", a1.menu[0], a1.menu[1], a1.menu[2])   # メニュー
    75				# 代入
    76	a2 = a1
    77	print("\n前 a1_size :", a1.getSize()[0], a1.getSize()[1])
    78	print("   a2_size :", a2.getSize()[0], a2.getSize()[1])
    79	a1.setSize(300, 600)   # サイズの変更
    80	print("後 a1_size :", a1.getSize()[0], a1.getSize()[1])
    81	print("   a2_size :", a2.getSize()[0], a2.getSize()[1])
    			
    11 行目~ 29 行目

      クラス Win に対する定義部分です.12 行目において,変数 name を文字列として定義しています.一般に,クラス内において,「 self.x 」の形で関数( Python においては,通常,メソッドと呼ぶ)の内側で定義される変数 x は,インスタンス変数と呼ばれ,各インスタンス固有の値を持つことが可能です.C++ における public 指定されたメンバー変数に似ており,どこからでも参照可能です.

      また,変数 name のように,関数の外側で宣言され,かつ,self がつかないクラス変数は,そのクラス及びクラスを継承したクラスのすべてのインスタンスで同じ値を持ち,
    	クラス名.変数名
    				
    のような形で参照可能です( 47 行目).このような点から,C++ における静的メンバー変数と似ています.しかし,その値を変更すると,参照方法によって異なってきます( 59 行目~ 64 行目).

      14 行目~ 17 行目では,関数 __init__ を定義しています.__init__ は,初期設定を行う関数であり,C++ におけるコンストラクタに似ています.ここでは,3 つのインスタンス変数 BGC,size,menu に対する初期設定を行っています.関数においては,その 1 番目の引数として self が渡されることに注意してください.

      19 行目では,関数 getBGC を定義しています.変数 BGC はどこからでも参照可能ですので,関数を使用せず,直接参照しても構いません( 52 行目).関数 getBGC は,インスタンスメソッドと呼ばれ,C/C++ におけるメンバー関数と似ています.

      21 行目では,関数 getSize を定義しています.変数 size はどこからでも参照可能ですので,関数を使用せず,直接参照しても構いません( 53 行目).関数 getBGC は,インスタンスメソッドと呼ばれ,C/C++ におけるメンバー関数と似ています.

      23 行目~ 25 行目では,name の値を取得する関数を,クラスメソッドとして定義しています.クラスメソッドは,「 @classmethod 」を付与して関数を定義します.クラスメソッドの場合は,第一引数にクラスが渡され,渡ってきたクラスを使ってクラス変数にアクセスすることができます.継承時には,第一引数に子クラスが渡されるため,クラス変数は子クラスのクラス変数の値となります( 65 行目).

      27 行目~ 29 行目では,name の値を取得する関数を,スタティックメソッドとして定義しています.スタティックメソッドは,「 @staticmethod 」を付与して関数を定義します.スタティックメソッドは,クラスが渡されないため,クラス変数にアクセスするためには,クラスを記述する必要があります.クラスを記述することによってクラス変数にアクセスするため,継承時においても,記述したクラスが親クラスか子クラスかによって参照先が変わります( 66 行目).

    34 行目~ 44 行目

      クラス Win (基底クラス)を継承するクラス App (派生クラス)に対する定義部分です.name の値は,57 行目に対応する出力結果からも明らかなように,クラス Win と同じになります.

      36 行目~ 38 行目は,App に対する関数 __init__ の再定義です.37 行目を記述しないと,Win クラスの __init__ をオーバーライドするだけになりますので,Win クラスの __init__ で定義した情報はすべて失われます.37 行目は,Win クラスの __init__ を実行するために必要となります.ここでは,それに加え,変数 menu に要素を一つ追加しています.

      40 行目~ 42 行目では,クラス App に新しく追加する関数 setSize を定義しています.もちろん,この関数によって変化するのは,クラス App のインスタンスの size だけです( 72 行目~ 73 行目).

      44 行目では,クラス App に新しく追加する関数 setBGC を定義しています.もちろん,この関数によって変化するのは,クラス App のインスタンスの BGC だけです( 68 行目~ 69 行目).

    76 行目~ 81 行目

      Ruby におけるクラスのインスタンス生成方法( 48 行目,59 行目)は,C++ における new 演算子を使用した方法( C++ に対するプログラム例の 100 行目)に非常に似ています.実際,変数 w1 や a1 には,インスタンスのアドレスが記憶されているとみることができます.従って,76 行目のような代入を行った場合,アドレス a1 が a2 にコピーされるわけですから,a1 と a2 は,同じ領域を指すことになり,a1 を介してその一部を変更すれば,a2 を介して見た内容も同じように変化します( 80 行目~ 81 行目).
      47 行目~ 81 行目内の出力文による出力結果です.ただし,コメント部分は対応する行番号であり,出力ではありません.
    Win_name : Window1   # 47 行目
    w1_name : Window1   # 49 行目
    w1_name(c) : Window1   # 50 行目
    w1_name(s) : Window1   # 51 行目
    w1_BGC : white   # 52 行目
    w1_size : 100 200   # 54 行目
    w1_menu : file edit   # 55 行目
    
    App_name : Window1   # 57 行目
    Win_name : Window1   # 58 行目
    App_name : Window2   # 62 行目
    Win_name : Window1   # 63 行目
    a1_name : Window3   # 64 行目
    a1_name(c) : Window2   # 65 行目
    a1_name(s) : Window1   # 66 行目
    a1_BGC : red   # 68 行目
    w1_BGC : white   # 69 行目
    a1_size : 200 400   # 72 行目
    w1_size : 100 200   # 73 行目
    a1_menu : file edit other   # 74 行目
    
    前 a1_size : 200 400   # 77 行目
       a2_size : 200 400   # 78 行目
    後 a1_size : 300 600   # 80 行目
       a2_size : 300 600   # 81 行目
    			

  7. C#

    01	/******************************/
    02	/* クラスに対するプログラム例 */
    03	/*      coded by Y.Suganuma   */
    04	/******************************/
    05	using System;
    06	using System.Collections.Generic;
    07	
    08	class Program
    09	{
    10		static void Main()
    11		{
    12				// クラス Win
    13			Console.WriteLine("Win_name : " + Win.name);   // 名前,static 指定のため可
    14			Console.WriteLine("Win_name : " + Win.getName());   // 名前,static 変数だけを参照可
    15			Win w1 = new Win("file", "edit");
    16	//		Console.WriteLine("w1_name : " + w1.name);   // 参照不可
    17			Console.WriteLine("w1_BGC : " + w1.getBGC());   // 背景色
    18			int[] s = w1.getSize();   // サイズの取得
    19			Console.WriteLine("w1_size : " + s[0] + " " + s[1]);
    20			Console.WriteLine("w1_menu : " + w1.menu[0] + " " + w1.menu[1]);   // メニュー
    21				// クラス App(クラス Win を継承)
    22			Console.WriteLine("\nApp_name : " + App.name);   // 名前,App.getName() でも可
    23			App a1 = new App("file", "edit");
    24	//		Console.WriteLine("a1_name : " + a1.name);   // 参照不可
    25			Console.WriteLine("a1_BGC : " + a1.getBGC());   // 背景色
    26			a1.setSize(200, 400);   // サイズの変更
    27			s = a1.getSize();
    28			Console.WriteLine("a1_size : " + s[0] + " " + s[1]);
    29			Console.WriteLine("w1_size : " + w1.getSize()[0] + " " +  w1.getSize()[1]);
    30			Console.WriteLine("a1_menu : " + a1.menu[0] + " " + a1.menu[1] + " " + a1.menu[2]);   // メニュー
    31				// 代入
    32			Console.WriteLine();
    33			App a2 = a1;
    34			Console.WriteLine("前 a1_size : " + a1.getSize()[0] + " " + a1.getSize()[1]);
    35			Console.WriteLine("   a2_size : " + a2.getSize()[0] + " " + a2.getSize()[1]);
    36			a1.setSize(300, 600);   // サイズの変更
    37			Console.WriteLine("後 a1_size : " + a1.getSize()[0] + " " + a1.getSize()[1]);
    38			Console.WriteLine("   a2_size : " + a2.getSize()[0] + " " + a2.getSize()[1]);
    39		}
    40	}
    41	
    42	/**************/
    43	/* クラス Win */
    44	/**************/
    45	class Win {
    46		public static String name = "Window1";   // 名前
    47		private String BGC = "white";   // 背景色
    48		protected int[] size = {100, 200};   // サイズ(縦と横)
    49		public List <String> menu = new List <String> ();   // メニュー
    50				// コンストラクタ
    51		public Win(String s1, String s2) {
    52			menu.Add(s1);
    53			menu.Add(s2);
    54		}
    55				// 名前の取得
    56		public static String getName() { return name; }
    57				// 背景色の取得
    58		public virtual String getBGC() { return BGC; }
    59				// サイズの取得
    60		public int[] getSize() { return size; }
    61	}
    62	
    63	/**************/
    64	/* クラス App */
    65	/**************/
    66	class App : Win {   // クラス Win を継承
    67				// コンストラクタ
    68		public App(String s1, String s2) : base(s1, s2)   // base は基底クラスのコンストラクタ
    69		{
    70			menu.Add("other");
    71		}
    72				// サイズの変更
    73		public void setSize(int row, int col)
    74		{
    75			size[0] = row;
    76			size[1] = col;
    77		}
    78				// 背景色の取得(基底クラスの private 変数にアクセスできない)
    79		public override String getBGC()
    80		{
    81	//		return BGC;   // アクセス不可
    82			return base.getBGC();
    83		}
    84	}
    			
    45 行目~ 61 行目

      クラス Win に対する定義部分です.46 行目において,変数( C++ におけるメンバー変数に相当) name を,String クラスのオブジェクトとして定義しています.String クラスは,文字列をサポートするクラスです.変数 name に対しては,static 指定が行われています.クラス内の変数に対して static 指定を行うと,静的メンバー変数となります.また,関数に対して static 指定を行うと,静的メンバー関数となりますが,その関数から参照できる変数は静的メンバー変数だけとなります.

      public 指定されていれば,静的メンバー変数や静的メンバー関数は,インスタンスを作成しなくても,
    	クラス名.静的メンバー変数名
    	クラス名.静的メンバー関数名
    				
    のような形で,どこからでも変数の参照や関数の実行が可能になります( 13 行目~ 14 行目).また,通常,インスタンスを生成すると,クラス内の変数はインスタンス毎にその値を変更できますが,静的メンバー変数の場合は,異なるインスタンスであっても,クラスが同じ,または,そのクラスを継承したクラスであれば同じ値となります( 13 行目~ 14 行目,22 行目に対する出力結果).ただし,16,24 行目のような「オブジェクト名.静的メンバー名」といった参照は不可能です.

      47 行目では,メンバー変数 BGC を String クラスのオブジェクトとして定義し,アクセス権として private を指定しています.private 指定された変数は,そのクラスに定義された関数( C++ におけるメンバー関数に相当,この例では,Win,getName,getBGC,getSize )だけから参照可能となります.ただし,静的メンバー関数 getName からは参照不可能です.なお,アクセス権を指定しないと private とみなされます.

      48 行目では,メンバー変数 size を,整数を要素とする配列として定義し,protected 指定しています.protected 指定された変数は,そのクラスに定義された関数( C++ におけるメンバー関数に相当,この例では,Win,getName,getBGC,getSize ),及び,そのクラスを継承したサブクラスだけから参照可能となります.ただし,静的メンバー関数 getName からは参照不可能です.

      49 行目では,メンバー変数 menu を,String クラスのオブジェクトを要素とする List クラスのオブジェクトとして定義しています.List クラスは,実行時における要素の追加や削除が可能である可変長の配列をサポートするクラスです.この変数に対しては,public 指定が行われており,どこからでも参照可能になります( 20 行目).

      51 行目~ 54 行目は,コンストラクタの定義です.コンストラクタはクラスのインスタンスを生成するとき( 15 行目),最初に呼ばれる関数であり,初期設定を行います.関数名は,クラス名と同じでなければならず,戻り値の型などを指定できません.ここでは,変数 menu に対する初期値を設定しています.

      56 行目では,静的メンバー関数 getName を定義しています.先に述べたように,静的メンバー関数は,静的メンバー変数だけを参照できますので,この例においては,参照できる変数は name だけになります.また,対象とする変数のアクセス権が public になっていますので,あえてメンバー関数を定義せず,13 行目のような形で直接参照することも可能です.

      58 行目では,メンバー関数 getBGC を定義しています.この関数が対象としている変数 BGC は private ですので,このような関数が存在しないと,変数 BGC を他のクラス(ここでは,クラス Program )から参照できなくなります.

      60 行目では,メンバー関数 getSize を定義しています.この関数が対象としている変数 size は protected ですので,このような関数が存在しないと,変数 size を他のクラス(ここでは,クラス Program )から参照できなくなります.

    66 行目~ 84 行目

      クラス Win (基底クラス)を継承するクラス App (派生クラス)に対する定義部分です.静的メンバー変数 name の値は,22 行目に対応する出力結果からも明らかなように,クラス Win と同じになります.

      68 行目~ 71 行目は,App に対するコンストラクタの定義です.ここでは,変数 menu に要素を一つ追加しています.コンストラクタは継承されませんので,スーパークラスのコンストラクタの呼び出しが必要な場合は,この位置において,明示的に呼び出す必要があります.この例では,クラス App のコンストラクターは引数を必要としませんが,クラス Win のコンストラクタは 2 つの引数を必要とします.そのため,クラス App のインスタンスを生成する際にも 2 つの引数が必要となり( 23 行目),その引数を使用し,「 : base(s1, s2) 」の記述によって,クラス Win のコンストラクタを呼んでいます.

      73 行目~ 77 行目では,クラス App に新しく追加するメンバー関数 setSize を定義しています.この関数が対象としている変数 size は protected ですので,クラス Win を継承したクラス App に新しく追加したメンバー関数からも参照可能です.もちろん,この関数によって変化するのは,クラス App のインスタンスにおける size だけです( 28 行目~ 29 行目).

      79 行目~ 83 行目は,メンバー変数 BGC の値を取得するために,クラス Win のメンバー関数 getBGC をオーバーライドしようとしています.勿論,この例の場合は,クラス Win の関数が継承され,そのまま使用できますので必要ありません.説明のために行っているだけです.

      まず,基底クラスの関数をオーバーライドするためには,基底クラスの関数において virtual の指定が必要であり( 58 行目),また,派生クラスにおいては,override の指定が必要になります( 79 行目).さらに,この関数の場合は,メンバー変数 BGC が private であり,クラス Win のメンバー関数だけからしか参照できません.そのため,ここでは,クラス Win の関数を呼んでいます( 82 行目).

    32 行目~ 38 行目

      C# におけるクラスのインスタンス生成方法( 15 行目,23 行目)は,C++ における new 演算子を使用した方法( C++ に対するプログラム例の 100 行目)に非常に似ています.実際,変数 w1 や a1 には,インスタンスのアドレスが記憶されているとみることができます.従って,33 行目のような代入を行った場合,アドレス a1 が a2 にコピーされるわけですから,a1 と a2 は,同じ領域を指すことになり,a1 を介してその一部を変更すれば,a2 を介して見た内容も同じように変化します( 37 行目~ 38 行目).
      13 行目~ 38 行目内の出力文による出力結果です.ただし,コメント部分は対応する行番号であり,出力ではありません.
    Win_name : Window1   // 13 行目
    Win_name : Window1   // 14 行目
    w1_BGC : white   // 17 行目
    w1_size : 100 200   // 19 行目
    w1_menu : file edit   // 20 行目
    
    App_name : Window1   // 22 行目
    a1_BGC : white   // 25 行目
    a1_size : 200 400   // 28 行目
    w1_size : 100 200   // 29 行目
    a1_menu : file edit other   // 30 行目
    
    前 a1_size : 200 400   // 34 行目
       a2_size : 200 400   // 35 行目
    後 a1_size : 300 600   // 37 行目
       a2_size : 300 600   // 38 行目
    			

  8. VB

    01	''''''''''''''''''''''''''''''
    02	' クラスに対するプログラム例 '
    03	'      coded by Y.Suganuma   '
    04	''''''''''''''''''''''''''''''
    05	Imports System
    06	Imports System.Collections.Generic
    07	
    08	Module Test
    09		Sub Main()
    10				' クラス Win
    11			Dim w1 As Win = new Win("file", "edit")
    12			Console.WriteLine("w1_name : " & w1.name)   ' 名前,a1.getName() でも可
    13			Console.WriteLine("w1_BGC : " & w1.getBGC())   ' 背景色
    14			Dim s() As Integer = w1.getSize()   ' サイズの取得
    15			Console.WriteLine("w1_size : " & s(0) & " " & s(1))
    16			Console.WriteLine("w1_menu : " & w1.menu(0) & " " & w1.menu(1))   ' メニュー
    17				' クラス App(クラス Win を継承)
    18			Console.WriteLine()
    19			Dim a1 As App = new App("file", "edit", 2)
    20			Console.WriteLine("a1_name : " & a1.getName())   ' 名前,a1.name でも可
    21			a1.name = "Window2"
    22			Console.WriteLine("a1_name(変更後) : " & a1.getName())   ' 名前,a1.name でも可
    23			Console.WriteLine("a1_BGC : " & a1.getBGC())   ' 背景色
    24			a1.setSize(200, 400)   ' サイズの変更
    25			s = a1.getSize()
    26			Console.WriteLine("a1_size : " & s(0) & " " & s(1))
    27			Console.WriteLine("w1_size : " & w1.getSize()(0) & " " &  w1.getSize()(1))
    28			Console.WriteLine("a1_menu : " & a1.menu(0) & " " & a1.menu(1) & " " & a1.menu(2))
    29			Console.WriteLine("x : " & a1.x(0) & " " & a1.x(1))   ' 配列 x
    30				' 代入
    31			Console.WriteLine()
    32			Dim a2 As App = a1
    33			Console.WriteLine("前 a1_size : " & a1.getSize()(0) & " " & a1.getSize()(1))
    34			Console.WriteLine("   a2_size : " & a2.getSize()(0) & " " & a2.getSize()(1))
    35			a1.setSize(300, 600)   ' サイズの変更
    36			Console.WriteLine("後 a1_size : " & a1.getSize()(0) & " " & a1.getSize()(1))
    37			Console.WriteLine("   a2_size : " & a2.getSize()(0) & " " & a2.getSize()(1))
    38		End Sub
    39	
    40		''''''''''''''
    41		' クラス Win '
    42		''''''''''''''
    43		Class Win
    44			Public name As String = "Window1"   ' 名前
    45			Private BGC As String = "white"   ' 背景色
    46			Protected size() As Integer = {100, 200}   ' サイズ(縦と横)
    47			Public menu As New List(Of String)   ' メニュー
    48				' コンストラクタ
    49			Public Sub New (s1 As String, s2 As String)
    50				menu.Add(s1)
    51				menu.Add(s2)
    52			End Sub
    53				' 名前の取得
    54			Public Function getName() As String
    55				Return name
    56			End Function
    57				' 背景色の取得
    58			Public Function getBGC() As String
    59				Return BGC
    60			End Function
    61				' サイズの取得
    62			Public Function getSize() As Integer()
    63				Return size
    64			End Function
    65		End Class
    66		
    67		''''''''''''''
    68		' クラス App '
    69		''''''''''''''
    70		Class App
    71			Inherits Win   ' クラス Win を継承
    72			Private BGC As String = "red"   ' 背景色
    73			Public x() As Integer
    74				' コンストラクタ
    75			Public Sub New (s1 As String, s2 As String, n As Integer)
    76				MyBase.new(s1, s2)   ' 基底クラスのコンストラクタ
    77				menu.Add("other")
    78				ReDim x(n)
    79				x(0) = 10
    80				x(1) = 20
    81			End Sub
    82				' サイズの変更
    83			Public Sub SetSize(row As Integer, col As Integer)
    84				size(0) = row
    85				size(1) = col
    86			End Sub
    87				' 背景色の取得(基底クラスの private 変数にアクセス不可)
    88			Public Overloads Function getBGC() As String
    89				Return BGC
    90			End Function
    91		End Class
    92	End Module
    			
    43 行目~ 65 行目

      クラス Win に対する定義部分です.44 行目において,変数( C++ におけるメンバー変数に相当) name を,String クラスのオブジェクトとして定義しています.String クラスは,文字列をサポートするクラスです.変数 name に対しては,Public 指定が行われていますので,どこからでも参照可能です.

      45 行目では,メンバー変数 BGC を String クラスのオブジェクトとして定義し,アクセス権として Private を指定しています.Private 指定された変数は,そのクラスに定義された関数( C++ におけるメンバー関数に相当,この例では,Win,getName,getBGC,getSize )だけから参照可能となります.

      46 行目では,メンバー変数 size を,整数を要素とする配列として定義し,protected 指定しています.protected 指定された変数は,そのクラスに定義された関数( C++ におけるメンバー関数に相当,この例では,Win,getName,getBGC,getSize ),及び,そのクラスを継承した派生クラスだけから参照可能となります.

      47 行目では,メンバー変数 menu を,String クラスのオブジェクトを要素とする List クラスのオブジェクトとして定義しています.List クラスは,実行時における要素の追加や削除が可能である可変長の配列をサポートするクラスです.この変数に対しては,Public 指定が行われており,どこからでも参照可能になります( 16 行目).

      49 行目~ 52 行目は,関数 Sub New の定義です.Sub New という関数が存在すると,クラスのインスタンスを生成するとき( 11 行目),最初に呼ばれます.C++ などにおけるコンストラクタに相当し,初期設定を行います.ここでは,変数 menu に対する初期値を設定しています.

      54 行目~ 56 行目では,関数 getName を定義しています.対象とする変数 name のアクセス権が Public になっていますので,あえてメンバー関数を定義せず,12 行目のような形で直接参照することも可能です.

      58 行目~ 60 行目では,メンバー関数 getBGC を定義しています.この関数が対象としている変数 BGC は Private ですので,このような関数が存在しないと,変数 BGC を他のクラスや関数(ここでは,関数 Main )から参照できなくなります.

      62 行目~ 64 行目では,メンバー関数 getSize を定義しています.この関数が対象としている変数 size は Protected ですので,このような関数が存在しないと,変数 size を他のクラスや関数(ここでは,関数 Main )から参照できなくなります.

    70 行目~ 91 行目

      クラス Win (基底クラス)を継承するクラス App (派生クラス)に対する定義部分です.71 行目のように,Inherits を使用して継承するクラスを記述します.

    73 行目

      配列 x を定義しています.ただし,この段階では,そのサイズを決められませんので,大きさが 0 である配列になっています.大きさは,クラス App のインスタンスを生成する際に引数として渡されてきますので,78 行目において,ReDim を使用して大きさの変更を行っています.

      75 行目~ 81 行目は,App に対するコンストラクタの定義です.ここでは,変数 menu に要素を一つ追加しています.コンストラクタは継承されませんので,基底クラスのコンストラクタの呼び出しが必要な場合は,この位置において,明示的に呼び出す必要があります.この例では,クラス App のコンストラクターは 1 つの引数だけを必要としすが,クラス Win のコンストラクタは 2 つの引数を必要とします.そのため,クラス App のインスタンスを生成する際にも 3 つの引数が必要となり( 19 行目),その引数を使用し,「 MyBase.new(s1, s2) 」によって,クラス Win のコンストラクタを呼んでいます.

      83 行目~ 86 行目では,クラス App に新しく追加するメンバー関数 setSize を定義しています.この関数が対象としている変数 size は Protected ですので,クラス Win を継承したクラス App に新しく追加したメンバー関数からも参照可能です.もちろん,この関数によって変化するのは,クラス App のインスタンスにおける size だけです( 26 行目~ 27 行目).

      88 行目~ 90 行目は,メンバー変数 BGC の値を取得するために,クラス Win のメンバー関数 getBGC をオーバーライドしようとしています.勿論,この例の場合は,クラス Win の関数が継承され,そのまま使用できますので必要ありません.説明のために行っているだけです.ただし,クラス Win とは異なる BGC の値を設定したい場合は必要です.基底クラスの関数をオーバーライドするためには,Overloads の指定が必要になります( 88 行目).さらに,この関数の場合は,メンバー変数 BGC が Private であり,クラス Win のメンバー関数だけからしか参照できません.そのため,ここでは,クラス App にも変数 BGC を定義しています( 72 行目).従って,この関数によって得られるのは,72 行目で定義された BGC の値です( 23 行目).

    31 行目~ 37 行目

      VB におけるクラスのインスタンス生成方法( 11 行目,19 行目)は,C++ における new 演算子を使用した方法( C++ に対するプログラム例の 100 行目)に非常に似ています.実際,変数 w1 や a1 には,インスタンスのアドレスが記憶されているとみることができます.従って,32 行目のような代入を行った場合,アドレス a1 が a2 にコピーされるわけですから,a1 と a2 は,同じ領域を指すことになり,a1 を介してその一部を変更すれば,a2 を介して見た内容も同じように変化します( 36 行目~ 37 行目).
      12 行目~ 37 行目内の出力文による出力結果です.ただし,コメント部分は対応する行番号であり,出力ではありません.
    w1_name : Window1   // 12 行目
    w1_BGC : white   // 13 行目
    w1_size : 100 200   // 15 行目
    w1_menu : file edit   // 16 行目
    
    a1_name : Window1   // 20 行目
    a1_name(変更後) : Window2   // 22 行目
    a1_BGC : red   // 23 行目
    a1_size : 200 400   // 26 行目
    w1_size : 100 200   // 27 行目
    a1_menu : file edit other   // 28 行目
    x : 10 20   // 29 行目
    
    前 a1_size : 200 400   // 33 行目
       a2_size : 200 400   // 34 行目
    後 a1_size : 300 600   // 36 行目
       a2_size : 300 600   // 37 行目
    			

静岡理工科大学 菅沼ホーム 目次 索引