インタフェース yukita@k.hosei.ac.jp プログラミング 第14回 インタフェース yukita@k.hosei.ac.jp プログラミング第14回
インタフェースとは クラスと同様の参照型の一種 フィールド,メソッドをもつ フィールドは定数だけが許される メソッドはすべて abstract,つまり実装されない abstract class では部分的に実装が可能 abstract class と同様にインスタンスは作れない Java言語におけるオブジェクトはこれですべて。 クラス クラスのインスタンス インタフェース プログラミング第14回
インタフェースによる契約 interface InterfaceX { public void methodX1(); } このインタフェースを実装するものを以下甲という。 このインタフェースを実装するクラスを,どのようなクラスであるか関心をもたずに信じて利用するものを以下乙という。 プログラミング第14回
インタフェースの実装者(契約者甲) public class ClassB implements InterfaceX { ClassC otsu; ... public void methodX1(){ } public void myInit(){ otsu=new ClassC(); otsu.setKo(this); 「InterfaceXに定められたメソッド群をすべて実装していますよ。」という宣言。これによりこのクラスは本来の型であるClassBだけでなく,InterfaceXという型ももつことになる。 プログラミング第14回
インタフェースの利用者(契約者乙) public class ClassC { InterfaceX ko; pubic void setKo(Interface ko){ this.ko=ko; } private void someMethod(){ ko.methodX1(); ... このクラスはInterfaceXを実装しているクラスならどんなクラスであろうと信じて使う。だから変数koの型はインタフェースで宣言している。実際にどのようなクラスがsetKo()で渡されて来ても,その中身には関知しない。 プログラミング第14回
多重継承とインタフェース 1つのクラスで複数のインタフェースを実装することができる。 多くの型をもつことができる。これは多重継承を実質可能にしている。abstract クラスではこのようなことができない。 プログラミング第14回
例 クラス図 <<interface>> X <<interface>> Y 例 クラス図 <<interface>> X <<interface>> Y <<interface>> Z ClassA ClassB ClassC プログラミング第14回
この結果 X[]={new A(), new B()}; X x=new B(); Y y=new B(); Z z=new B(); のようなことができる。 プログラミング第14回
Lockable.java(List 14-1,p.167) interface Lockable { boolean lock(); boolean unlock(); } プログラミング第14回
Kinko.java(List 14-2, p.108)完全版 class Kinko implements Lockable{ private boolean locked=false; public boolean isLocked(){ return locked;} public boolean lock(){ if(locked==false){ locked=true; System.out.println("Lockされました。"); }else{ System.out.println("すでにLockされています。"); } return locked; プログラミング第14回
Kinko.java (2) public boolean unlock(){ if(locked==true){ locked=false; System.out.println("Lockが解除されました。"); }else{ System.out.println("Lockされていません。"); } return locked; プログラミング第14回
LockableTest.java public class LockableTest{ public static void main(String[] args){ Lockable x; x=new Kinko(); x.lock(); x.unlock(); } プログラミング第14回
実行結果 Lockされました。 Lockが解除されました。 プログラミング第14回
課題 Lockableインタフェースを実装するクラスHouseを作成せよ。 lock されると「準備中」とprintする unlock されると「営業中」とprintする LockableTestを改造し,LockableTest2とせよ。 Lockableの長さ2の配列にKinkoとHouseのインスタンスを格納し,動作を検証する。 プログラミング第14回
解答例 House.java(1) class House implements Lockable{ private boolean locked=false; public boolean isLocked(){ return locked;} public boolean lock(){ if(locked==false){ locked=true; System.out.println("準備中"); }else{ System.out.println("既に準備中ですよ。"); } return locked; プログラミング第14回
House.java (2) public boolean unlock(){ if(locked==true){ locked=false; System.out.println("営業中"); }else{ System.out.println("既に営業中ですよ。"); } return locked; プログラミング第14回
解答例 LockableTest2.java public class LockableTest2{ public static void main(String[] args){ Lockable[] x=new Lockable[2]; x[0]=new Kinko(); x[1]=new House(); x[0].lock(); x[0].unlock(); x[1].lock(); x[1].unlock(); } プログラミング第14回
余裕のある人へ 次に紹介するのは swing の JFrame を拡張し,Lockable インタフェースを実装するクラスの例である。 単体テストのためのmainメソッドも用意してある。 結合テストドライバとして LockableTest3 を用意してある。 長さ3の配列 x[]にKinko,House,SwingKinkoのインスタンスを格納している。 コマンドプロンプトからインデックスと“lock”または“unlock”をスペースで区切って入力する。 どういう動きをするだろうか。 プログラミング第14回
SwingKinko.java (1) import java.awt.*; import java.awt.event.*; import javax.swing.*; class SwingKinko extends JFrame implements Lockable, ActionListener{ private boolean locked; private JButton lock, unlock, quit; private JTextField message; private JPanel jp; プログラミング第14回
SwingKinko.java (2) public SwingKinko(){ super("Swing Kinko"); setGUI(); } public boolean lock(){ locked=true; message.setText("ロックされています"); return locked; public boolean unlock(){ locked=false; message.setText("ロック解除中"); プログラミング第14回
SwingKinko.java (3) private void setGUI(){ jp=new JPanel(); getContentPane().add(jp); lock=new JButton("Lock"); lock.addActionListener(this); unlock=new JButton("Unlock"); unlock.addActionListener(this); quit=new JButton("Quit"); quit.addActionListener(this); message=new JTextField(30); message.setEditable(false); プログラミング第14回
SwingKinko.java (4) jp.add(lock); jp.add(unlock); jp.add(quit); jp.add(message); setSize(new Dimension(400,100)); setVisible(true); } プログラミング第14回
SwingKinko.java (5) public void actionPerformed(ActionEvent e){ Object obj=e.getSource(); if(obj==lock){ lock(); } else if (obj==unlock){ unlock(); } else if (obj==quit){ System.exit(0); } プログラミング第14回
SwingKinko.java (6) // For unit test public static void main(String[] args){ new SwingKinko(); } プログラミング第14回
LockableTest3.java (1) import java.io.*; public class LockableTest3{ public static void main(String[] args){ Lockable[] x ={new Kinko(),new House(),new SwingKinko()}; BufferedReader reader =new BufferedReader( new InputStreamReader(System.in),1); String line, token1, token2; int target=0; int sep; プログラミング第14回
LockableTest3.java (2) try{ while(!((line=reader.readLine()).equals("quit")) && (sep=line.indexOf(" "))>0){ token1=line.substring(0,sep).trim(); token2=line.substring(sep+1).trim(); target=Integer.parseInt(token1); if(token2.equals("lock")){ x[target].lock(); }else if(token2.equals("unlock")){ x[target].unlock(); } プログラミング第14回
LockableTest3.java (3) }catch(IOException e){System.exit(1); }catch(NumberFormatException e){System.exit(2); } System.exit(0); プログラミング第14回
ActionListenerインタフェースの契約 JButton のインスタンスたちは契約者乙 addActionListener(甲)により契約希望者の登録を待つ。 登録されている甲に対して,必要なときにactionPerformed()を呼び出す。 SwingKinko のインスタンスは契約者甲 actionPerformed()をしっかり定義する義務がある。 プログラミング第14回
ActionListener契約開始 lock:JButton unlock:JButton quit:JButton addActionListener(this); SwingKinko プログラミング第14回
ActionListener契約履行と仕事の連携 ボタンが押された lock:JButton unlock:JButton quit:JButton actionPerformed(actionEvent); どの契約者乙からやって来たか判別して,それに応じて処理をおこなう。 SwingKinko プログラミング第14回