Java初心者です。

Javaの書籍で、ポリモーフィズムを説明している箇所において
オブジェクトを生成する際に、以下のような書き方をしているのを見ます。

1.-----
スーパークラス名 オブジェクト名 = new サブクラスのコンストラクタ名();
--------

上記は、
何を実現する為に、左辺と右辺のクラス名とコンストラクタ名を変えているのでしょうか?
(もちろん詳細は実際に書かれたメソッドや変数によると思いますが、一般的な話として。)
また併せて、

2.-----
サブクラス名 オブジェクト名 = new サブクラスのコンストラクタ名();
-------
と書いた時とでは、使用(アクセス)出来るメソッドや変数、
生成されたオブジェクトの中身が、どのように変わってくるのでしょうか?
2.の方法では、何が実現出来ないのでしょうか?

教えて下さい!

このQ&Aに関連する最新のQ&A

A 回答 (5件)

>これは、


>-----
>ArrayList list= new ArrayList();
>-----
>と書いても同じだと感じるのですが、違うのでしょうか?
>この辺りがちょっと分かっておりません。
>
>こう書けばいいものをナゼわざわざ
>List list= new ArrayList();
>って書くのかな~と、、、
>初心者なんで細かいところで足踏みしてしまうのです。。。

まず、開発というものは非常多くの事を考慮して行います。
その考慮を推し量れないとこのような疑問が出てくるのだと思います。
その理由はこの一行だけでは誰もわからないでしょう。

>List list= new ArrayList();

この一行だけで意味を見つけるのだとしたら、
listというオブジェクトに制約を設けるためです。
インターフェースは定義だと前のレスで書きましたが、
このインスタンスはListというインターフェースの定義で使用する
事を強要するという事です。
この場合はArrayListのインスタンスであるにも関わらず、
Listに無いメソッドやグローバル変数にはアクセスができなくなります。

コードというものは様々なコードとの整合性を考える必要があります。
そういいた意味で、この一行だけでなくプログラム全体を見通した時、
>List list= new ArrayList();
という一行に意味を持つ事もあります。

これ以上の説明は設計という作業に関係してきます。
まさに題名の「ポリモーフィズム」とはそういう類のものです。
「インターフェース」「設計」などで検索をされてはいかがでしょうか?

あなたが探している答えは実際にこの書き方をされている
コードの中にあると思います。
    • good
    • 0
この回答へのお礼

>コードというものは様々なコードとの整合性を考える必要があります。
>そういいた意味で、この一行だけでなくプログラム全体を見通した時、
>>List list= new ArrayList();
>という一行に意味を持つ事もあります。

なるほど!そういった類いのものなんですね、ありがとうございます。

お礼日時:2011/04/29 12:08

ここで詳しい説明をするのは大変なので、キーワードだけ。



1) OCP(Open Close Principle)
2) 共通-可変性分析
3) 上位の共通化
4) 抽象化
5) 処理の違い=具象オブジェクトの違い

いずれもオブジェクト指向分析でアプリケーションの構造を決定するときに
用いられるものです。いずれもポリモーフィズムが関連します。

このあたりを調べると、ポリモーフィズムがオブジェクト指向を支えている
ものであることが判ると思います。
    • good
    • 0
この回答へのお礼

ありがとうございます!

学ぶべきキーワードを教えて下さると、次のステップにつながるので助かります!

Java、深いですね、、、おもしろいです。

お礼日時:2011/04/29 10:47

No.2さんの回答がしっくり来ますね。



>これは、java.io.Writer / java.io.Reader などがよく例に挙げられます。
>メソッドに引数には、スーパークラスで定義し、実装ではサブクラスを与えるといった使い方です。

ただ、この部分ですが、
この記述はインターフェースこ事だと思われます。
サブクラスは機能拡張、インターフェースは定義ですから。


あくまで私の使用例ですが、
1.の場合はポリモーフィズムにて、インスタンスを持たせたオブジェクトメソッドの
処理内容を切り替えたいときに使用します。
例えば、ある条件ではスーパークラス(インターフェース)ではなく
サブクラス(実装クラス)のオーバーライド(実装)された同名のメソッドを使用するということです。
これはインターフェースとしての使い方です。
サブクラスは既存クラスに対し、何らかの追加機能をする時や既存機能を
改ざんしたい時にのみ使用します。
例えば、ArrayListを使用しているプログラムにデバッグ用に中のデータを表示したいとします。
そのためにdebug()というメソッドを追加してSystem.outへ内容を出力させる処理を追加。
というような使い方ですね。
この場合、ArrayListを継承しているため、コードの変更は不必要になります。

ArrayList list = new DebugableArrayList();
list.add("a");
((DebugableArrayList)list).debug();

のような使い方ですね。


2.についてはそもそも普通の使い方がありますので特に意識はしません。

>と書いた時とでは、使用(アクセス)出来るメソッドや変数、
>生成されたオブジェクトの中身が、どのように変わってくるのでしょうか?
>2.の方法では、何が実現出来ないのでしょうか?

例えば、

List list= new ArrayList();

とした時を考えてください。
list.add("a");
とした時に呼び出されるaddの処理はListではなくArrayListのaddの処理が呼び出されます。
ちなみにもし、Lsitのaddを呼び出したい場合は実装クラスのaddメソッド内で
super.add()という処理を書けばアクセスできます。
(Listはインターフェースなので処理は実際に書かれていないのでが・・・)

何が実現できないとかというよりも目的が違います。

本当はこの技術については非常に高度な設計が絡んできますのでこの場所で説明は無理です。

この回答への補足

皆さんご丁寧に回答して下さって、本当にありがとうございます!

covachan様から頂いた回答に更に質問ですが、

>例えば、
>
>List list= new ArrayList();
>
>とした時を考えてください。
>list.add("a");
>とした時に呼び出されるaddの処理はListではなくArrayListのaddの処理が
>呼び出されます。

これは、
-----
ArrayList list= new ArrayList();
-----
と書いても同じだと感じるのですが、違うのでしょうか?
この辺りがちょっと分かっておりません。

こう書けばいいものをナゼわざわざ
List list= new ArrayList();
って書くのかな~と、、、
初心者なんで細かいところで足踏みしてしまうのです。。。

補足日時:2011/04/25 23:10
    • good
    • 0

一般的にプログラミングを行う上では、


2.の書き方をしても、1.の書き方をすることは滅多にありません。
使用するスコープ内で、わざわざスーパークラスにダウンキャストしても、
使用できるメソッドが制限されるデメリットのみで、得られるメリットはありません。
書籍上で、機能の説明をするために記述してあると考えられます。

2.の記述では出来て、1.の記述でしかできないことはありませんが、その逆はあります。
実際に生成されたオブジェクト (インスタンス)の内容が変わるといったことはありません。

では、どういう時に例題のようなポリモーフィズムを利用するかというと、
メソッドや、コンストラクタの引数に利用する際です。
これは、java.io.Writer / java.io.Reader などがよく例に挙げられます。
メソッドに引数には、スーパークラスで定義し、実装ではサブクラスを与えるといった使い方です。

他にも、もう少し高度になると Factory を使用した際にも有効になります。
これは、Springframework や S2 といったフレームワークを使うようになると、
その利便性が体感できると思います。
    • good
    • 0

例えば



「学校の関係者」
というスーパークラスがあります
サブクラスとして
「教師」「生徒」「PTA」なんかがあります。

「学校の関係者」 田中先生 = new 「教師」();
「学校の関係者」 山田さん = new 「生徒」();
のような感じですか。
これは、処理の中で「学校の関係者」であることを求められているときに利用します。
つまり、田中先生や山田さんが教師だろうが生徒だろうが関係ないような場合ですね。
例えば「学校の関係者」共通の権限の判定に使ったりします。
他にも「学校の関係者」には共通のメソッドがあり
その結果だけが重要でその処理内容はどうでもいい場合にも利用します。

「教師」 田中先生 = new 「教師」();
「生徒」 山田さん = new 「生徒」();
こうする場合は、処理の中で教師であること、生徒であることを明確に区別する必要があるときに利用します。
例えば「教師」特有「生徒」特有の権限の判定に使ったりします。
他にも「教師」や「生徒」専用のメソッドを使うためにはこうしないと利用できません(キャストすれば別ですが)。


まあ、一番多いのはメソッドの利用ですね。
メソッド=権限ですし。
    • good
    • 0

このQ&Aに関連する人気のQ&A

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人が検索しているワード

このQ&Aと関連する良く見られている質問

Qinterface,extend,implementのちがい

お世話になります、

Javaを勉強しているのですが、
interface,extend,implementの使い分けがわかりません。

私の解釈としては、
(1)interfaceは、グローバル変数の定義、グローバルメソッドの定義(実装はしない)。

(2)extendは、extendクラスを親クラスとして親クラスの機能を使用できる。

(3)implementは…,implementもextendと同じような意味だと解釈しているんですが、違う点は、implementで定義してあるメソッドは、使用しなくても、実装しなければならないという点でしょうか?

とにかくこの3つのを使い分けるコツとかあれば教えてください。
よろしくお願いします。

Aベストアンサー

バラバラに理解してもしょうがないッス。

まず、
(1)interface と implements
(2)class と extends

が対応しているわけっす。

JavaはC++と違って、比較的言語仕様を「簡単」にしたので「多重継承」という
概念がないです。
多重継承っていうのは、複数のクラスを親クラスにして継承するってことですね。

たとえば、 「TextFieldクラス」と「Japaneseクラス」を多重継承すると、
「JTextFieldクラス」ができるっていうのが自然な考え方でしょう?

まぁ、例えば、日本語クラスであれば、getStringLength()メソッドなどが
あったほうが良いでしょうか。
このgetStringLength()メソッドは、2バイト文字も1バイト文字も「1文字」
と数えてくれると言う点で、まさに、日本語クラス用のメソッドだと言えるでしょう。

例えば、Java的に記述すると、、、
class Japanese {
public int getStringLength() {
  ・・・
return strlength;
 }
 ・・・
}

class TextField {
・・・
}

class JTextField extends TextField, extends Japanese {
・・・・
}

C++ではそのように実装するでしょう。
しかし、Javaにはこのような高度な機能はありません。

そこで、生まれた苦肉の策が、「interfaceとimplements」です。

interface Japanese {
public int getStringLength(); // interfaceは実装を含まない!
                 // すなわち「実装の継承」ができるわけではない。
}

class TextField {
・・・
}

class JTextField extends TextField implements Japanese {
・・・・
public int getStringLength() {
  ・・・
return strlength; //implementsの実装を「各クラスで」実装してやる必要がある。
 }
}


結局のところ、Javaでは、複数のクラスを親クラスには持ち得ないため、継承できなかったクラスは「各クラスで実装してやる必要性」があるのです。


ではどのように使うのが効果的か?

なまえのままです。「代表的なインターフェイス」にたいしてinterfaceを使うのが良いと思います。

例えば、プレイヤー系であれば、ビデオ・コンポ・ウォークマン・などにかかわらず、
interface controlpanel {
public play();
public stop();
public next();
public back();
}
というような基本的インターフェイスを「持っているべき」です。

こうすることで、それぞれのクラス宣言の際に、これらの「インターフェイスを持っているべきであり、実装されるべきである」ということを「強く暗示」することができます。
class videoplayer extends player implements controlpanel {
public play() {・・・}
public stop() {・・・}
public next() {・・・}
public back() {・・・}
}

こうすることで、同様のクラスを作成するユーザーは、
「プレイヤー系は、4つ操作が出来るコントロールパネルをインターフェイスとして持つべきなのだな!?」という暗示を受け取り、自分のクラスでもそれを模倣するでしょう。

class mp3player extends player implements controlpanel {
public play() {・・・}
public stop() {・・・}
public next() {・・・}
public back() {・・・}
}

また、これらのクラスを使用するユーザーも、「implements controlpanel」という
表記を見て、「4つの基本操作は押さえられているのだな!」という基本中の基本動作を抑えることが出来ます。

まとめると、クラスに「こういう特徴もたしてください!」「こういう特徴持ってますよ!」という一種の暗示的警告や方向性を与えることができるわけですね。

バラバラに理解してもしょうがないッス。

まず、
(1)interface と implements
(2)class と extends

が対応しているわけっす。

JavaはC++と違って、比較的言語仕様を「簡単」にしたので「多重継承」という
概念がないです。
多重継承っていうのは、複数のクラスを親クラスにして継承するってことですね。

たとえば、 「TextFieldクラス」と「Japaneseクラス」を多重継承すると、
「JTextFieldクラス」ができるっていうのが自然な考え方でしょう?

まぁ、例えば、日本語クラスであれば...続きを読む

Qシンボルが見つかりませんというエラーが理解できません。

以下のようなじゃんけんゲームのプログラムを書いたのですが、「シンボルが見つかりません。」というエラーが表示されるのですが、エラーの意味が理解できず、解決できません。どこが間違っているのか教えていただけませんか。

import java.applet.Applet;
import java.awt.*;
import java.awt.event.*;
import java.io.File;

public class janken extends Applet
implements Runnable, ActionListener {
private static final int EXTERNAL_BUFFER_SIZE = 128000;

Image image[] = new Image[3];
Thread t;
int index1 = 0;
int index2 = 0;
String msg = "";
String msg1 = "";

boolean state = false;
Button b1 = new Button("ぐー");
Button b2 = new Button("ちょき");
Button b3 = new Button("ぱー");

public void init(){
for(int i = 0; i<=2; i++){
img[i] = getImage(getDocumentBase(),"hanabi" + (i+1) + ".JPG");
}
add(b1);
add(b2);
add(b3);
b1.addActionListener(this);
b2.addActionListener(this);
b3.addActionListener(this);
msg1 = "結果は・・";

}

public void paint(Graphics g){
g.drawImage(img[index1],350,30,this);
g.drawImage(img[index2],695,30,this);
g.drawString("コンピューター",420,300);
g.drawString("あなた",800,300);
g.drawString(msg,630,320);
g.drawString(msg1,550,320);
}

public void start(){
state = true;
t = new Thread(this);
t.start();

}

public void run(){
while(state){
index1++;
if(index1 == 3){
index1 = 0;
}
index2++;
if(index2 == 3){
index2 = 0;
}
repaint();
try {
Thread.sleep(60);
}catch(InterruptedException e) { }
}
}

public void actionPerformed(ActionEvent e){
if(state == false) {
start();
return;

}
state = false;
if(e.getSource() == b1) {
msg = "ぐー";
index2 = 0;
}

else if(e.getSource() == b2){
msg = "ちょき";
index2 = 1;
}

else if(e.getSource() == b3){
msg = "ぱー";
index2 = 2;
}
check();
repaint();
}

public void check() {
if(index1 == index2) msg ="あいこ";


else if (index1 == 0) {
if(index2 == 2) msg="あなたの勝ち";
else msg ="あなたの負け";
}

else if(index1 == 1) {
if(index2 == 0) msg="あなたの勝ち";
else msg="あなたの負け";
}

else if(index1 == 2) {
if(index2 == 1) msg="あなたの勝ち";
else msg="あなたの負け";
}

}
}

以下のようなじゃんけんゲームのプログラムを書いたのですが、「シンボルが見つかりません。」というエラーが表示されるのですが、エラーの意味が理解できず、解決できません。どこが間違っているのか教えていただけませんか。

import java.applet.Applet;
import java.awt.*;
import java.awt.event.*;
import java.io.File;

public class janken extends Applet
implements Runnable, ActionListener {
private static final int EXTERNAL_BUFFER_SIZE = 128000;

Image image[] = new Imag...続きを読む

Aベストアンサー

「シンボルを見つけられません。」というエラーの下に何か表示がありませんでしたか?そこにヒントがあると考えられます。
シンボルを見つけられませんといエラーが表示される主な理由は4つあります。
(1)クラス、メソッド、変数などの綴りミスや定義していない変数を使用している可能性がある。
(2)コンストラクタを呼び出すときに、newを忘れている可能性がある。(3)公開されていないメンバーを呼び出している可能性がある。
(4)必要なimport文を記述し忘れている可能性がある。
ここでのあなたのエラーは(1)番ではないでしょうか?上記ではimageとなっている変数がimgになっていますね。
これはエラー表示をよく見ることで意外と簡単に解決できるのです。
ゆっくり丁寧にエラー表示を見るように心がけることが大事ですよ。

QArrayListの使い方がわかりません。(超初心者です。)

情報管理用のクラス[Hito]を作成する。
プロパティ
 String name
double taijyu
double sincho
double nenrei

・メインクラスでHitoをArrayListに5つ格納し、それぞれの値を表示させるという課題に挑んでいます。

2週間前からjavaを勉強し始めたばかりで、ようやくオブジェクト指向や、クラスというものどんなものか多少イメージがわいてきた程度です。ArrayListについては配列と違い、格納するデータ数の数をはじめから決めなくてもいいというぐらいしかわかっていません。(これでさえ違うかも?)

 どのように組みはじめばいいか、そしてArrayListはどのように使えばいいのか教えていただけますか? よろしくお願いします。

Aベストアンサー

ほかの方の説明で理解を深めたら、以下のコーディングを打ち込んでコンパイルします。
C:\java\OKWeb>javac TestHito.java
成功したら、

C:\java\OKWeb>java TestHito
で実行してみてください。
C:\java\OKWeb>java TestHito
名前 あきら 体重 74.3 身長 184.3 年齢 35
名前 まみ 体重 44.5 身長 168.4 年齢 28

と表示されます。
先ず動く事で感動を得る事が大切だと思います。
import java.util.*;

class Hito {
private String name;
private double taijyu;
private double sincho;
private int nenrei;

public Hito(){
name="";
taijyu=0;
sincho=0;
nenrei=0;
}

public void setName(String name){
this.name = name;
}
public void setTaijyu(double taijyu){
this.taijyu = taijyu;
}
public void setSincho(double sincho){
this.sincho = sincho;
}
public void setNenrei(int nenrei){
this.nenrei = nenrei;
}
public String getName(){
return name;
}
public double getTaijyu(){
return taijyu;
}

public double getSincho(){
return sincho;
}
public int getNenrei(){
return nenrei;
}
}

public class TestHito{


public static void main(String []args){
Hito[] hito =new Hito[5];
for(int i = 0; i < 5; i++){
hito[i] = new Hito();
}
hito[0].setName("あきら");
hito[1].setName("まみ");
hito[0].setTaijyu(74.3);
hito[1].setTaijyu(44.5);
hito[0].setSincho(184.3);
hito[1].setSincho(168.4);
hito[0].setNenrei(35);
hito[1].setNenrei(28);
ArrayList result = new ArrayList();
result.add(hito[0]);
result.add(hito[1]);
for(int i = 0; i<result.size(); i++){
hito[i]=(Hito)result.get(i);
System.out.println("名前 "+hito[i].getName()+
" 体重 "+hito[i].getTaijyu()+
" 身長 "+hito[i].getSincho()+
" 年齢 "+hito[i].getNenrei());
}

}
}

ほかの方の説明で理解を深めたら、以下のコーディングを打ち込んでコンパイルします。
C:\java\OKWeb>javac TestHito.java
成功したら、

C:\java\OKWeb>java TestHito
で実行してみてください。
C:\java\OKWeb>java TestHito
名前 あきら 体重 74.3 身長 184.3 年齢 35
名前 まみ 体重 44.5 身長 168.4 年齢 28

と表示されます。
先ず動く事で感動を得る事が大切だと思います。
import java.util.*;

class Hito {
private String name;
private double taijyu;
private double sincho;
...続きを読む

Q2つの項目が重複するレコードを抽出する方法はありますか?

MySQL4.1で既存データに対し複合キーを新しく設定したいのですが、

ALTER TABLE `test` ADD PRIMARY KEY (`a`,`b`)

としても重複データが存在する為、作成できませんでした。

10万件あるテーブルから重複するレコードを手動で削除したいのですが、aとbが重複しているレコードだけ抽出するSQL文はありますでしょうか?

Aベストアンサー

select * from `test`
where (a,b) in(
select a,b from `test`
group by a,b
having count(*)>1)

QSELECTで1件のみ取得するには?

こんにちわ。
いまORACLE9iを使用している者です。

ACCESSでは
SELECT TOP 1 項目名 FROM テーブル名
ORDER BY 項目名;
で並べ替えたデータ群のうち,先頭の1件だけを
取ることができますが,
ORACLEでそのような機能(SQL)はあるでしょうか?
教えてください。
よろしくお願いします。

Aベストアンサー

order by と rownum を併用する場合は注意が必要です。

[tbl01]
cola | colb
------------
1000 | aaaa
1001 | bbbb

というデータがある場合、
select cola from tbl01 where rownum < 1 order by cola desc;
とすると、「1001」ではなく、「1000」が返されます。
これは、order by の前に rownum < 1 が適用されてしまうからです。

解決するには、
select aaa from (select cola aaa from tbl01 order by cola desc) where rownum = 1;
とすれば良いです。


人気Q&Aランキング

おすすめ情報