NetBeansでPHPUnitを使った単体テストの実験をしてみた

NetBeans IDE 7.0.1でPHPUnitを使った単体テストの実験をしてみた。オプション設定で躓いたので備忘録的にまとめておきます。

1:メニューから[ツール]>[オプション]を選択する。
2:単体テストタブを選択する。
3:PHPUnit スクリプトC:\xampp\php\phpunit.bat から参照する。
スクリプトが表示されていない場合は参照します。参照先を探すのに苦労した(´>ω<`)

後は、本家チュートリアルを見ながら単体テストを実行できます。

さくらのVPSでHinemosをセットアップしてみた(2)

前回、Hinemosのマネージャサーバとクライアントのインストールをしました。
マネージャサーバへ接続するためにポート開放をする必要がありました(´>ω<`)

SSH                         TCP 22
HTTP                        TCP 80
Hinemosクライアント     TCP 1098,1099,4444,4445,4446
Hinemosジョブエージェント  TCP 4457
Hinemosログ転送エージェント TCP 24457

[参考:install.pdf 3.5.2 マネジャサーバへの接続]

iptablesは、パケットフィルタリング機能を提供するプログラムで、ファイアーウォールの構築などに利用されます。未設定の状態からSSH、HTTP、Hinemosの利用に必要なポート解放し、後は利用しないようにします。とりあえず必要最小限の設定を行なってみます。

現在のiptablesの設定を確認してみます。

$ sudo iptables -L
Chain INPUT (policy ACCEPT)
target     prot opt source               destination         
 
Chain FORWARD (policy ACCEPT)
target     prot opt source               destination         
 
Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination

何にも設定されていません・・・、全裸待機でした(´・ω・`)ショボーン
ポート開放の設定をしてる内にデータが消えてたみたいです。ということで・・・気を取り直してiptablesを設定します。

最初に、さくらVPSiptablesがインストールされていることを確認します。

$ yum list installed | grep iptables
iptables.x86_64                           1.3.5-5.3.el5_4.1            installed
iptables-ipv6.x86_64                      1.3.5-5.3.el5_4.1            installed

iptablesの設定は /etc/sysconfig/iptables に記述します。初期状態ではこのファイルが存在しないので新規作成します。root権限の必要な場所に保存するので sudo vi で作成します。

$ sudo vi /etc/sysconfig/iptables

以下の様に記述します。

※サーバの環境に応じて必要なポートを開放します。SSHでの接続は公開鍵認証のみにする。

*filter
:INPUT	ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:RH-Firewall-1-INPUT - [0:0]

-A INPUT -j RH-Firewall-1-INPUT
-A FORWARD -j RH-Firewall-1-INPUT
-A RH-Firewall-1-INPUT -i lo -j ACCEPT
-A RH-Firewall-1-INPUT -p icmp --icmp-type any -j ACCEPT
-A RH-Firewall-1-INPUT -p 50 -j ACCEPT
-A RH-Firewall-1-INPUT -p 51 -j ACCEPT
-A RH-Firewall-1-INPUT -p udp --dport 5353 -d 224.0.0.251 -j ACCEPT
-A RH-Firewall-1-INPUT -p udp -m udp --dport 631 -j ACCEPT
-A RH-Firewall-1-INPUT -p tcp -m tcp --dport 631 -j ACCEPT
-A RH-Firewall-1-INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

#SSH,HTTP
-A RH-Firewall-1-INPUT -m state --state NEW -m tcp -p tcp --dport 22 -j ACCEPT
-A RH-Firewall-1-INPUT -m state --state NEW -m tcp -p tcp --dport 80   -j ACCEPT

#Hinemos
-A RH-Firewall-1-INPUT -m state --state NEW -m tcp -p tcp --dport 1098 -j ACCEPT
-A RH-Firewall-1-INPUT -m state --state NEW -m tcp -p tcp --dport 1099 -j ACCEPT
-A RH-Firewall-1-INPUT -m state --state NEW -m tcp -p tcp --dport 4444 -j ACCEPT
-A RH-Firewall-1-INPUT -m state --state NEW -m tcp -p tcp --dport 4445 -j ACCEPT
-A RH-Firewall-1-INPUT -m state --state NEW -m tcp -p tcp --dport 4446 -j ACCEPT
-A RH-Firewall-1-INPUT -m state --state NEW -m tcp -p tcp --dport 4457 -j ACCEPT
-A RH-Firewall-1-INPUT -m state --state NEW -m tcp -p tcp --dport 24457 -j ACCEPT

-A RH-Firewall-1-INPUT -j REJECT --reject-with icmp-host-prohibited

COMMIT

iptablesの設定については、http://www.nina.jp/server/redhat/iptables/iptables.html
設定ファイルが作成されたのでiptablesを再起動します。

$ sudo /etc/rc.d/init.d/iptables restart
Flushing firewall rules:                                   [  OK  ]
Setting chains to policy ACCEPT: filter                    [  OK  ]
Unloading iptables modules:                                [  OK  ]
Applying iptables firewall rules:                          [  OK  ]

最後に設定を確認します。

$ sudo iptables -L

これでクライアントからマネージャサーバへ接続することが可能になりました(´・ω・`)

さくらのVPSでHinemosをセットアップしてみた(1)

さくらVPSでHinemosのセットアップに挑戦してみました(`・ω・´)
VPSのコントロールパネルからも十分にサーバーの情報を見ることができるのですが、複数のサーバーを管理するときに一つ一つ手作業するよりも効率良く運用できるツールみたいなので勉強も兼ねてセットアップしてみました。


そもそもHinemosとは何ぞ?ということで、簡単にまとめると・・・。
複数のコンピューターを単一のコンピューターのイメージで運用管理することができるソフトウェアでNTTデータが提供するOSS(オープンソフトウェア)になっています。大規模システムの統合管理をすることが可能で運用目的ごとに様々な環境をクライアント側から一元管理することができる機能を備えています。


主に4つの機能があり、「リポジトリ管理」「ジョブ管理」「性能管理」「監視管理」をすることができます。
(1)リポジトリ管理
・管理対象を自由にグルーピングすることができる。
・グループ毎にバッチ処理をすることが可能。
(2)ジョブ管理
・ジョブネットによる効率化
・複数サーバーを一括制御
・カレンダー運用
(3)性能管理
・リアルタイム性能グラフ表示
リポジトリの情報に対応
・実績性能情報収集機能
CSV形式でのファイル出力
(4)監視管理
Pingの死活
SQL監視
・HTTP監視

などの結果を画面上で確認することができます。


Hinemosは下記3つの機能で構成されています。
・マネージャ:システムの監視、ジョブの実行、設定の管理などを行う
・クライアント:マネージャに接続して監視の状態などをチェックしたり、設定を行うコンソール
・エージェント:管理対象コンピュータにインストールしてマネージャからの監視、制御に応答する
※今回はServerにマネージャー、PCにクライアントをインストールする手順までをやります。


以下、HinemosをさくらVPSでのセットアップ手順をまとめてみました。
■構築環境
Server:さくらVPS OS:CentOS 5.5 x86_64
PC OS:Windows Vista


▽マネージャーの設定(Serverにインストールします。)
1:Hinemosのマネジャーをダウンロード
(hinemos_agent-3.2.2_rhel5_32.tar.gz)
2:VPSにある適当なフォルダーにコピーします。
※今回は解凍先ディレクトリを”/tmp”にしています。
3:rootユーザで、hinemos_manager-3.2.0_rhel5_32.tar.gzを/tmpディレクトリに展開します。

# cd /tmp
# tar -zxvf hinemos_manager-3.2.2_rhel5_32.tar.gz

4:/tmpディレクトリ直下に、Hinemos_Manager-3.2.2_rhel5_32ディレクトリが作成されます。
解凍されたHinemos_Manager-3.2.2_rhel5_32ディレクトリに移動します。

# cd /tmp/Hinemos_Manager-3.2.2_rhel5_32/

5:rootユーザで、manager_installer_JP.shを実行します。

# ./manager_installer_JP.sh

6:インストールを開始しますか?というメッセージが表示されるので[Y]。
7:パスワードの入力を求められます。ユーザhinemosのパスワードを入力します

ユーザ hinemos の確認中...
New UNIX password:(パスワードを入力します)
Retype new UNIX password:(パスワードを再入力します)

※注意:よく間違えるポイントとしては、ここでのパスワードはVPS側のhinemosユーザにアクセスするためのもので、クライアントからマネージャーにログインする際に必要となるパスワードとは別になるの注意する。
8:マネージャサーバのIPアドレスの入力が求められので、さくらVPSIPアドレスを入力します。確認のメッセージが表示されるので[Y]。
9:FTPサーバのIPアドレスの入力が求められるので、FTPサーバのIPアドレスを入力します。ここでがデフォルトの設定をしました。
確認のメッセージが表示されるので、そのまま[Y]。
10:設定項目の入力が完了するとマネージャーのインストールが開始されます。

マウントされているファイルシステム一覧
/dev/sda2 - /
/dev/sda1 - /boot
データベースディレクトリ(/opt/hinemos/var/data)はパーティション / 内に格納されます。
ログディレクトリ(/opt/hinemos/var/log)はパーティション / 内に格納されます。
必要なファイルのコピー実行中... [OK]
設定ファイル(hinemos.cfg, LogForward.properties, selfcheck-service.xml)の生成中... [OK]

以上で、Hinemosマネージャのインストールは完了です。

[参考サイト]
Hinemos http://www.hinemos.info/


Hinemosマネージャーの起動方法

# cd /opt/hinemos/bin
# ./hinemos_start.sh

Hinemosマネージャーの停止方法

# cd /opt/hinemos/bin
# ./hinemos_stop.sh

HinemosマネージャをOS起動時から有効にするための設定
サービス化するためにrootユーザで以下のコマンドを実行し、サービス起動スクリプトを配置します。

# cd /tmp/Hinemos_Manager-3.2.2_rhel5_32/hinemos/sbin/service/
# cp hinemos_manager /etc/init.d/

自動起動の設定

# chkconfig --add hinemos_manager


▽クライアントの設定(操作するPCにインストールします。)
1:Hinemosクライアントダウンロード
(HinemosClientInstaller-3.2.2_winvista_32.msi
2:ダウンロードしたインストーラをセットアップ手順に従ってインストールします。
3:プログラムからHinemos3.2.2を起動します。

最後に、インストールが完了したらHinemosクライアントを起動します。
以下のログイン情報を入力します。

ユーザ:hinemos
パスワード:hinemos
接続先URL:jnp://さくらVPSのアドレス

※注意:ユーザ/パス:hinemos/hinemosは初期パスワードになっています。
マネージャー側のパスワードと混同しないように^^;


次回は、実際にリポジトリに登録して運用方法などについてまとめたいと思います(´・ω・`)

JAVAでSQLiteを使ってみた

JavaSQLiteを使うための簡単なプログラムを書いてみます。

SQLiteの特徴の特徴としては、

  • Cで書かれた軽量データベース
  • 全体のコード数が10万行程度
  • データベースを保存するファイルが1つに納まっている

他のシステムだと、複数のデータベース用のファイルがあって管理が面倒なのですが、SQLiteのデータベースはファイル1つで、しかもOS互換フォーマットで保存されているので、簡単にOSをまたがったデータベースのコピーを作成することができます。


データベースアプリケーションを作成するには、JDBCというAPIを使います。SQLite JDBC Driverを使ってローカルにデータベースを作成してみます。先ず、Java用のライブラリーをダウンロードして、プロジェクトのビルド・パスに追加します。


SqliteJDBC(Java用のライブラリ:jarファイル)
http://www.zentus.com/sqlitejdbc/
SQLite JDBC Driverは、Mac OS X, Windows, Linuxなどよく使われるOSでSQLiteをインストールなしで動作させるために、それぞれのOSでコンパイルしたSQLiteのバイナリをjarファイルの中に埋め込んであります。プログラムの実行時に、自動的にjarファイルの中からOSに応じたSQLiteのバイナリを取り出しJava側でロードして使えるようになります。

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

public class SQLtest {

	private static Connection conn;
	private static Statement stmt;
	private static ResultSet rs;

	public static void main(String[] args)  {

		try {
			//準備(Cドライブにあるsqlite_sampleフォルダに作成します)
			Class.forName("org.sqlite.JDBC");
			conn = DriverManager.getConnection("jdbc:sqlite:/c:/sqlite_sample/testdatabase");
			stmt = conn.createStatement();

			//テーブル作成
			stmt.executeUpdate("create table test1( name string, age integer )" );

			//値を入力する
			stmt.execute( "insert into test1 values ( '初音ミク', 16 )" );

			//結果を表示する
			rs = stmt.executeQuery("select * from test1");
			while(rs.next()) {
				System.out.println(rs.getString("name"));
				System.out.println(rs.getInt("age"));
			}

		} catch (ClassNotFoundException e) {
			// TODO 自動生成された catch ブロック
			e.printStackTrace();
		} catch (SQLException e) {
			// TODO 自動生成された catch ブロック
			e.printStackTrace();
		} finally {
			if(conn != null) {
				try {
					//接続を閉じる
					conn.close();
				} catch (SQLException e) {
					// TODO 自動生成された catch ブロック
					e.printStackTrace();
				}
			}
		}
	}
}

【JAVA】ニコニコ動画のXMLをJSON化してみた

お久しぶりです、マキ猫です(*゚∀゚)
JAVAを勉強して初めて作ったWebサービスが「VOCALO-TREND.com」なのですが、当初考えてた以上に沢山の人に使って頂きありがとうございました♫ 「初音ミクみく」さんや「ニコラジ」さんにもサイトを紹介して頂いて作って良かったなぁって思ってます(*´ω`*)
かなり稚拙なプログラミングでJavaを使っておきながら、クライアントサイドなjavaScriptでゴリゴリ動かす仕様なので若干重めになっています^^;;
ならば直接サーバーサイドで書いてみたらと言うことで「niconico4J」という面白いJarを見つけてきたので、早速ニコニコ動画XMLJSON化するサンプルプログラムを書いてみました。

package niconico;

import java.io.InputStream;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.xml.bind.DatatypeConverter;

import net.arnx.jsonic.JSON;
import analyzer.GetFlvXmlPather;
import bean.TagBean;
import bean.ThumbInfoBean;
import connect.HttpConnector;

public class XML_To_Json {
	
public static void main(String[] args){
	Map<String, Object> map1_1 = new HashMap<String, Object>();
	map1_1.put("hashtag", "sm14917720");
	map1_1.put("count_tw", "10");
	map1_1.put("max_rt", "5");
	map1_1.put("count_rt", "12");
	map1_1.put("total_points", "117");
	
	Map<String, Object> map1_2 = new HashMap<String, Object>();
	map1_2.put("hashtag", "sm14285610");
	map1_2.put("count_tw", "30");
	map1_2.put("max_rt", "5");
	map1_2.put("count_rt", "10");
	map1_2.put("total_points", "315");
		
	Map<String, Object> map1_3 = new HashMap<String, Object>();
	map1_3.put("hashtag", "sm7");
	map1_3.put("count_tw", "20");
	map1_3.put("max_rt", "0");
	map1_3.put("count_rt", "12");
	map1_3.put("total_points", "212");
		
	Map<String, Object> map1_4 = new HashMap<String, Object>();
	map1_4.put("hashtag", "sm14917525");
	map1_4.put("count_tw", "20");
	map1_4.put("max_rt", "0");
	map1_4.put("count_rt", "12");
	map1_4.put("total_points", "212");
		
	try {
		List<Map<String, Object>> list1 = new ArrayList<Map<String,Object>>();
		list1.add(map1_1);
		list1.add(map1_2);
		list1.add(map1_3);
		list1.add(map1_4);
			
		//System.out.println(JSON.encode(list1, true));
		//System.out.println("-----");
			
		List<Map<String,Object>> list2 = new ArrayList<Map<String,Object>>();
			
		for(int i = 0; i < list1.size() ; i++){
			HttpConnector connector = new HttpConnector();
			InputStream id = connector.getVideoInfo((String) list1.get(i).get("hashtag"));
			
			GetFlvXmlPather pather = new GetFlvXmlPather();
			ThumbInfoBean thumbInfo = pather.getFlv(id);
			
			String status = thumbInfo.getResponseStatus();
			
			if(status.equals("ok")){
				SimpleDateFormat dateFormatter_nicodate = new SimpleDateFormat("yyyy年MM月dd日 kk時mm分 ");
				Calendar nicodate =DatatypeConverter.parseDateTime(thumbInfo.getFirstRetrive());
				String date = dateFormatter_nicodate.format(nicodate.getTime());
					
				String videoId = thumbInfo.getVideoId();
				String title = thumbInfo.getTitle();
				String watchUrl = thumbInfo.getWatchUrl();
				String thumbnailUrl = thumbInfo.getThumbnailUrl();
				String length = thumbInfo.getLength();
				String viewCounter = DecimalFormat(thumbInfo.getViewCounter());
				String commentNum = DecimalFormat(thumbInfo.getCommentNum());
				String mylistCounter = DecimalFormat(thumbInfo.getMylistCounter());
				String description = thumbInfo.getDescription();
				String lastResBody = thumbInfo.getLastResBody();
				
				Map<String, Object> nicoMap = new HashMap<String, Object>();
				Map<String, Object> nicoStatus = new HashMap<String, Object>();
				
				nicoMap.put("nicoStatus",nicoStatus);
				
				nicoMap.put("nicoTitle",title);
				nicoMap.put("nicoDate",date);
				nicoMap.put("nicoId",videoId);
				nicoMap.put("nicoUrl",watchUrl);
				nicoMap.put("nicoThumb",thumbnailUrl);
				nicoMap.put("nicoLength",length);
				nicoMap.put("nicoCountView",viewCounter);
				nicoMap.put("nicoCountComment",commentNum);
				nicoMap.put("nicoCountMylist",mylistCounter);
				nicoMap.put("nicoDescription",description);
				nicoMap.put("nicoLastResBody",lastResBody);
				
				ArrayList<TagBean> tagArray = thumbInfo.getTagArray();
				ArrayList<String> tagList = new ArrayList<String>();
				for(TagBean tag:tagArray){
					if(tag.getDomain().equals("jp")){
						tagList.add(tag.getTag());
					}
				}
				nicoMap.put("tag", tagList);
				list2.add(nicoMap);
			}else{
				Map<String, Object> nicoMap = new HashMap<String, Object>();
				nicoMap.put("nicoId", list1.get(i).get("hashtag"));
				nicoMap.put("nicoStatus",status);
				list2.add(nicoMap);
			}
		}
			
		for (Map<String, Object> map1 : list1) {
			List<Map<String, Object>> data = new ArrayList<Map<String,Object>>();
			for (Map<String, Object> map2 : list2) {
				if (map1.get("hashtag").equals(map2.get("nicoId"))) {
					data.add(map2);
				}
			}
			map1.put("nicoInfo", data);
		}
		System.out.println(JSON.encode(list1, true));
	} catch (Exception e) {
		e.printStackTrace();
	}
}
public static String DecimalFormat(Object object) {
	DecimalFormat df1 = new DecimalFormat("###,###,###");
	return df1.format(object);
}
}

動画が削除されている場合、nicovideo_thumb_responseのStatus値が"fail"になるのですが、JSON化するときに動画情報と同じテーブルに組み込まれてしまっているので使い勝手は悪いかもしれないので改良の余地はあるかも。
テストでサーバーサイドとクライアントサイドで使用してみたんですけど、体感速度的にはあまり違いを感じなかったので現状そのままにしています。
(※DBの負荷がネックになってるのは置いといてw)
将来的にサイトデザインをリニューアルしたり、ブログパーツ化するときに全部まとめて取得できるのでその時にでも考えようと思います(´・ω・`)

【Java】インターフェースと抽象クラス

インターフェース

前回、立方体の体積を求めるメソッドをインターフェースThreeDで宣言し、立方体を定義するクラスBoxに多重継承して具体的なメソッドを記述しました。

public interface ThreeD {
    //体積を計算するための抽象メソッド
	public int calcVolume();
}
//implements - インターフェース、extend - 継承
public class Box extends Rect implements ThreeD {
	.....
	//体積を求める
	public int calcVolume(){
        //インターフェースで宣言された抽象メソッドに具体的なメソッドを記述します
		return super.calcArea() * this.length;
	}
}

抽象クラスとは

メソッドの名前と引数の型だけ定まっていて、その本体(実装)がないメソッドのことを抽象メソッドと呼びます。抽象メソッドを含んでいるクラスを抽象クラスと呼びます。抽象クラスにはabstractという修飾子がつきます。では、具体的な例として抽象クラスFigをクラスRectのスーパークラスにしてみます。

public abstract class Fig {
	//デフォルトコンストラクタ
    //抽象クラスFigを親にもつサブクラスはインスタンス化されるたびコンソールにFigと表示
	public Fig(){
		System.out.println("Fig");
	}
	
	//抽象メソッド:面積の計算、親の命令は必ず子にも実装しないとエラーになる
	public abstract int calcArea();
}
public class Rect extends Fig {
    .....
	
	//メソッド
	//面積の計算
	public int calcArea(){
		return this.height * this.width;
	}
	.....
}

まとめ

抽象メソッドを記述した抽象クラスを親にもつサブクラスは、必ず抽象メソッドを実装しなければなりません。抽象クラスは自分では動作を規定しないけれど、どういうメソッドが必要なのかをサブクラスに指示しているのです。つまり抽象クラスを使うことでサブクラスのメソッドが揃うため、読みやすいプログラムを記述することができます。

【Java】スーパークラスとサブクラス

スーパークラスとサブクラスとは

クラスは拡張することができます。すでに存在するクラスをもとにして、それに新しいメソッドやフィールドを追加したり上書きしたりして新しいクラスを宣言することができます。クラスを拡張してできた新しいクラスを、もとのクラスのサブクラスと呼びます。また逆に、元のクラスを、拡張してできたクラスのスーパークラスと呼びます。

extendsでスーパークラスを指定

それでは長方形大きさや面積、周長を定義したクラスRectを宣言します。次に立方体の大きさや表面積、体積を定義したクラスBoxを宣言します。継承を行うためにはextendsを使用します。クラス名の後ろにextendsを記述し継承したいクラスを指定します。ここではboxというクラスを宣言しています。後ろにextends Rectと記述しています。このように書くことでBoxがRectのサブクラスであることを表します。

public class Box extends Rect{
	.....
}
/*
継承の構文
class サブクラス名 extends スーパークラス名{
    .....
}
*/

継承とは

サブクラスは、スーパークラスのフィールドとメソッドを受け継ぎます。このことを継承といいます。フィールドとメソッドは継承されますが、コンストラクタは継承されません。これはJava言語の文法規則です。それでは長方形を定義するクラスRectのフィールドとメソッドを継承して立方体を定義するクラスを記述してみます。

public class Rect{

	//フィールド
	private int width; //幅
	private int height; //高さ
	
	//デフォルトコンストラクター
	public Rect(){
		this(0,0);
	}
	
	
	//コンストラクター
	public Rect(int width, int height) {
		this.width = width;
		this.height = height;
	}
	
	//メソッド
	//面積を計算
	public int calcArea(){
		return this.width * this.height;
	}
	
	//周りの長さ
	public int calcLength(){
		return (this.width + this.height) * 2;
	}
	
	//getter & setter
	public int getWidth() {
		return width;
	}
	public void setWidth(int width) {
		this.width = width;
	}
	public int getHeight() {
		return height;
	}
	public void setHeight(int height) {
		this.height = height;
	}
}

スーパークラスを継承する

クラスRectのサブクラスであるクラスBoxにはクラスRectのコンストラクタは継承されないので、フィールドに奥行きの情報を加えて立方体を定義するコンストラクタを生成します。

public class Box extends Rect{
	
	//フィールド設定
	private int length; //奥行き
	
	//デフォルトコンストラクター
	public Box(){
		this(0,0,0);
	}
	
	//コンストラクター
	public Box(int width,int height,int length){
		super(width,height);
		this.length = length;
	}
	.....
}

スーパークラスの呼び出し

立方体の面積を計算するのに、長方形で定義したクラスRectのメソッドcalcAreaとフィールドwidth、heightを継承をつかって呼び出します。スーパークラスのフィールドやメソッドを呼び出すにはsuperの後にフィール名やメソッド名を.ピリオドでつなぎます。

public class Box extends Rect{
    .....
    //表面積の計算
	public int calcArea(){
		return (super.calcArea() * 2) + (this.length * super.getHeight() *2) + (this.length * super.getWidth() * 2);
	}
}
public class Box extends Rect{
    .....
    //全周の長さ
	public int calcLength() {
		return (super.calcLength()*2) + (this.length * 4);
	}
}

インターフェースによる多重継承

Java言語では多重継承はサポートされていませんが、インターフェースという仕組みを使うことで擬似的に多重継承を実現することができます。

インターフェースとは

クラスは参照型の一種で、名前やフィールド、メソッドを持ち、スーパークラスやサブクラスを持っています。インターフェースも参照型の一種です。名前やフィールドを持ち、スーパーインターフェースやサブインターフェースを持ちます。クラスとインターフェースの違いは、次の点で異なります。
・インターフェースが持つフィールドは必ず定数
・インターフェースが持つメソッドは必ず抽象メソッド()
※抽象メソッド:{中括弧}内に具体的な処理を記述しないメソッド
・インターフェースはインスタンスをつくることができない

インターフェースの宣言

それでは実際にインターフェースをつかってみます。新しく立方体の体積を計算するクラス、ここで言うインターフェースをつくります。
interfaceという単語は、Java言語の予約語で、インターフェースの宣言の始まりを表します。宣言されたメソッドには本体({中括弧}でくくられた部分)がない抽象メソッドになります。interfaceの中に宣言されているメソッドはabstractが付いていなくても自動的に抽象メソッドになります。つまり、interfaceのなかに{中括弧}があるメソッドは宣言できないということです。

public interface ThreeD {
    //体積を計算するための抽象メソッド
	public int calcVolume();
}

インターフェースの実装

インターフェースの実装にはimplementsという予約語を使います。
それでは、先程の立方体の表面積や周長を計算するクラスBoxにインターフェースThreeDを実装してみます。

//implements - インターフェース、extend - 継承
public class Box extends Rect implements ThreeD {
	.....
	//体積を求める
	public int calcVolume(){
        //インターフェースで宣言された抽象メソッドに具体的なメソッドを記述します
		return super.calcArea() * this.length;
	}
}

完成

Java言語でプログラムを書くということは、クラスを宣言し、フィールドを作り、メソッドを設計して、それを実装することです。もしも、過去に作られたクラスを全く利用できなかったら、すべてをゼロからプログラミングしなければなりません。スーパークラスのフィールドやメソッドを継承することで、同じフィールドやメソッドを再度プログラミングするひつようが無くなるのです。

public class Box extends Rect implements ThreeD {
	
	//1フィールド設定
	private int length; //奥行き
	
	//2デフォルトコンストラクター
	public Box(){
		this(0,0,0);
	}
	
	//2コンストラクター
	
	public Box(int width,int height,int length){
		super(width,height);
		this.length = length;
	}
	

	//メソッド
	//表面積の計算
	public int calcArea(){
		return (super.calcArea() * 2) + (this.length * super.getHeight() *2) + (this.length * super.getWidth() * 2);
	}

	//全周の長さ
	public int calcLength() {
		return (super.calcLength()*2) + (this.length * 4);
	}

	//体積を求める
	public int calcVolume(){
        //インターフェースで宣言された抽象メソッドに具体的なメソッドを記述します
		return super.calcArea() * this.length;
	}
}
public class Sample {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		
		//Rectを利用
		System.out.println("Rectを利用");
		Rect rect = new Rect(); //インスタンス化
		rect.setWidth(10);
		rect.setHeight(20);
		
		System.out.println("幅=" + rect.getWidth());
		System.out.println("高さ=" + rect.getHeight());
		
		System.out.println("面積=" + rect.calcArea());
		System.out.println("周りの長さ=" + rect.calcLength());
		
		Box box = new Box(5,5,10);
		System.out.println("面積=" + box.calcArea());
		System.out.println("周りの長さ=" + box.calcLength());
		System.out.println("体積=" + box.calcVolume());
	}

}