- PR -

Genericsとオーバーロード

1
投稿者投稿内容
くれよん
ベテラン
会議室デビュー日: 2005/04/28
投稿数: 74
投稿日時: 2006-10-27 16:00
こんにちわ。いつも勉強させていただいています。
Generics?についての質問です。
現在、次のようなDataSaverというクラスを使用してます。
DataSaver2のようにsaveDataというメソッドに統一したいと思い、Genericsを調べましたが、上手くプログラムを書くことができません。そもそもこの様な書き方は可能なのでしょうか?どなたがご教授お願いします。

public class DataSaver {
/** 保存先のディレクトリ */
private String BaseURL;
private boolean showFlg;

/**
* コンストラクタ
* @param _BaseURL
*/
public DataSaver(String _BaseURL,boolean _showFlg){
BaseURL = _BaseURL;
showFlg = _showFlg;
}

/**
* データの保存LinkedList<Integer>
* @param fileName
* @param data
*/
public void saveDataI(String fileName, LinkedList<Integer> data){
if(data==null)return;
String S="";
for(int i=0;i<data.size();i++){
S += data.get(i) +"\n";
}
try{
write(BaseURL+fileName,S);
if(showFlg)System.out.println(BaseURL+fileName);
}catch(Exception e){
}
}

/**
* データの保存LinkedList<Double>
* @param fileName
* @param data
*/
public void saveDataD(String fileName, LinkedList<Double> data){
if(data==null)return;
String S="";
for(int i=0;i<data.size();i++){
S += data.get(i) +"\n";
}
try{
write(BaseURL+fileName,S);
if(showFlg)System.out.println(BaseURL+fileName);
}catch(Exception e){
}
}

/**
* テキストファイルへ保存
* @param fileName
* @param S
* @throws IOException
*/
private synchronized void write(String fileName,String S) throws IOException{
RandomAccessFile writer = new RandomAccessFile(fileName,"rw");
writer.seek(writer.length());
StringBuffer sb = new StringBuffer();
sb.append(S);
sb.append("\n");
String log = new String(sb);
writer.writeBytes(log);
writer.close();
}
}


public class DataSaver2 {
/** 保存先のディレクトリ */
private String BaseURL;
private boolean showFlg;

/**
* コンストラクタ
* @param _BaseURL
*/
public DataSaver2(String _BaseURL,boolean _showFlg){
BaseURL = _BaseURL;
showFlg = _showFlg;
}

/**
* データの保存LinkedList<Integer>
* @param fileName
* @param data
*/
public void saveData(String fileName, LinkedList<Integer> data){
if(data==null)return;
String S="";
for(int i=0;i<data.size();i++){
S += data.get(i) +"\n";
}
try{
write(BaseURL+fileName,S);
if(showFlg)System.out.println(BaseURL+fileName);
}catch(Exception e){
}
}

/**
* データの保存LinkedList<Double>
* @param fileName
* @param data
*/
public void saveData(String fileName, LinkedList<Double> data){
if(data==null)return;
String S="";
for(int i=0;i<data.size();i++){
S += data.get(i) +"\n";
}
try{
write(BaseURL+fileName,S);
if(showFlg)System.out.println(BaseURL+fileName);
}catch(Exception e){
}
}

/**
* テキストファイルへ保存
* @param fileName
* @param S
* @throws IOException
*/
private synchronized void write(String fileName,String S) throws IOException{
RandomAccessFile writer = new RandomAccessFile(fileName,"rw");
writer.seek(writer.length());
StringBuffer sb = new StringBuffer();
sb.append(S);
sb.append("\n");
String log = new String(sb);
writer.writeBytes(log);
writer.close();
}
}
山本 裕介
ぬし
会議室デビュー日: 2003/05/22
投稿数: 2415
お住まい・勤務地: 恵比寿
投稿日時: 2006-10-27 16:05
全部読んでくれる人がいると良いですが・・・。
ちょっとだけ確認するのはしんどいです。

もうすこし本質的になにがわからないのか端的に表現するため、コードを短くして提示することはできないでしょうか?
くれよん
ベテラン
会議室デビュー日: 2005/04/28
投稿数: 74
投稿日時: 2006-10-27 16:25
お返事ありがとうございます。
質問内容を省略したものを以下に書きます。

DataSaverクラスに次の二つのメソッドがあります。
saveDataI(String fileName, LinkedList<Integer> data)
saveDataD(String fileName, LinkedList<Double> data)

この二つのメソッドをDataSaver2クラスにあるようにオーバーロードで
以下の様にしたいのです。
saveData(String fileName, LinkedList<Integer> data)
saveData(String fileName, LinkedList<Double> data)
しかしこのままでは引数が同じだと判断されてコンパイルエラーが返ってきます。
Genericsを用いれば可能かと思い調べましたが、上手くプログラムを書くことが出来ませんでした。そもそもGenericsを用いて、この様な事が実現可能でしょうか?

よろしくお願いします。
かずくん
ぬし
会議室デビュー日: 2003/01/08
投稿数: 759
お住まい・勤務地: 太陽系第三惑星
投稿日時: 2006-10-27 16:41
さくらばさんのサイトの「メソッドのパラメータ化」を読むと幸せになれるかもしれません。

追記:
Integerの場合とDoubleの場合で実装を買える場合は、たぶんムリでしょう。
(提示されたコードは、同じに見えた)。

[ メッセージ編集済み 編集者: かずくん 編集日時 2006-10-27 16:43 ]
nagise
ぬし
会議室デビュー日: 2006/05/19
投稿数: 1141
投稿日時: 2006-10-27 16:48
引用:

クレやんさんの書き込み (2006-10-27 16:25) より:
DataSaverクラスに次の二つのメソッドがあります。
saveDataI(String fileName, LinkedList<Integer> data)
saveDataD(String fileName, LinkedList<Double> data)

この二つのメソッドをDataSaver2クラスにあるようにオーバーロードで
以下の様にしたいのです。
saveData(String fileName, LinkedList<Integer> data)
saveData(String fileName, LinkedList<Double> data)
しかしこのままでは引数が同じだと判断されてコンパイルエラーが返ってきます。
Genericsを用いれば可能かと思い調べましたが、上手くプログラムを書くことが出来ませんでした。そもそもGenericsを用いて、この様な事が実現可能でしょうか?



結論から言えば不可能です。
ジェネリクスの型情報はコンパイル時のみの情報で、
実行時には失われています。
つまり、両方とも
saveData(String fileName, LinkedList data)
という宣言になってしまうわけです。

ただ、今回のケースだとIntegerのときもDoubleのときも
やっていることが変わらないので一緒くたに処理しちゃえばいいんじゃないかと。
もしくはIntegerとDoubleの共通のスーパークラスNumberにしてしまうとか。

saveData(String fileName, LinkedList<? extends Number> data)

そもそもLinkedListに限定する必要がないので
saveData(String fileName, List<? extends Number> data)
ぐらいが適当でしょうか。
java.util.Listで順序を保障する必要がなければ
java.util.Collectionにしても構いません。
くれよん
ベテラン
会議室デビュー日: 2005/04/28
投稿数: 74
投稿日時: 2006-10-27 17:00
お返事ありがとうございます。
かずくんさんのURLに掲載されていたワイルドカード<?>を用いたら上手くいきました。(←オーバーロードではなく、一つにまとめる事ができました)

nagiseさんありがとございます。僕のプログラムに無駄が沢山ある事よく分かります。
;´Д`A LinkedListに限定する全くないですね!大変勉強になりました。ありがとうございました。

[ メッセージ編集済み 編集者: クレやん 編集日時 2006-10-27 17:04 ]
1

スキルアップ/キャリアアップ(JOB@IT)