• ベストアンサー

JAVAでCの関数ポインタのようなことをするには?

CのプログラムをJAVAに移植しています。関数ポインタのプログラムを移植したいのですがやり方がよく判りません。interfaceを実装するとできるようですが・・・ 以下のCプログラムをJAVAに移植する方法を教えてください。 #include <stdio.h> int func(int , int); int main() { int (*po)(int , int) , i; po = func; i = (*po)(10 , 3); printf("%d" , i); return 0; } int func(int i , int j) { return i + j; }

質問者が選んだベストアンサー

  • ベストアンサー
  • Gishi
  • ベストアンサー率57% (11/19)
回答No.4

こんな感じでしょうか。   static interface Func {     int func(int i, int j);   }   static class FuncImpl implements Func {     public int func(int i, int j) {       return i + j;     }   }   public static void main(String[] args) {     Func po = new FuncImpl();     int i = po.func(10, 3);     System.out.println(i);   } ややこしいですね。 Javaにも関数ポインタがあればいいのに。 po に別の関数を代入したい場合は、   po = new AnotherFuncImpl(); のような形になります。

kahata
質問者

お礼

完璧な回答をありがとうございました。test proofです。 もうひとつ、別の質問になるかも知れないのですが、javaでphpの call_user_func_array()のようなことができればよいのですが・・・ つまり、関数名をstringで与えて動的に関数を呼び出す方法です。

その他の回答 (13)

回答No.14

/** 取り敢えずは、動くのを作ってみた。(但し、入力チェックは省略。) ご参考までに・・・。 http://itpro.nikkeibp.co.jp/article/lecture/20070131/260145/ http://lib.stwing.jp/archives/2006/02/call_user_funcc.html */ import java.util.*; import static java.lang.System.*; abstract class Func{  void call_user_func_array(String method, int[] array){   Func po;   int result = 0;   if(method.equals("SubFunc")){    po = new SubFunc();    result = po.func(array[0], array[1]);   }else if(method.equals("KoFunc")){    po = new KoFunc();    result = po.func(array[0], array[1]);   }else if(method.equals("fnctn")){    KoFunc popo = new KoFunc();    result = popo.fnctn(array[0], array[1]);   }   System.out.println("\n結果は、" + result + "です。");  }  abstract int func(int i, int j); } class SubFunc extends Func{  public int func(int i, int j){   return i + j; // 和  } } class KoFunc extends Func{  public int func(int i, int j){   return i - j; // 差  }  public int fnctn(int i, int j){ // 自作メソッド。   return i * j; // 積  } } class Polymorphism{ // 多態性。  static public void main(String... $_){ // JDK5。   int[] test = {10, 3};   KoFunc c_u_f_a = new KoFunc();   Scanner scan = new Scanner(in);   while(true){    System.out.println("\n 以下の何れかの文字を入力して、動的結合の開始。");    System.out.println("SubFunc");    System.out.println("KoFunc");    System.out.println("fnctn");    String line = scan.next();    c_u_f_a.call_user_func_array(line,test);    System.out.println("\n\n// 終了は、「Ctrl + Z」か、「Ctrl + C」で。");   }  } }

kahata
質問者

お礼

call_user_func_array()の件は余談のつもりでしたのに丁寧にフォローして頂きありがとうございます、面白いです。大変有用で参考になります。

回答No.13

連続失礼。 > dummy.GetTimes()のところでシンボルを解決出来ないというコンパイルエラーでした。 エラーの原因はtypoでした○| ̄|_

回答No.12

質問に対する回答じゃなくてすみませんが。 > ANo.2 参考サイト 読み直すと、インスタンスを生成して変数に入れるということをせずに、 関数呼び出しの引数のところで直接 new してるだけなのかなぁ。。 だとすると、オブジェクトを作ってそのメソッドを呼ぶのは関数ポインタとは関係なくて、 OOPそのものじゃないかなと思いますが。。。 (Raise2()の例が微妙ですが、、、) class Hand{  private int t;  public void Hand(){   t=0;  }  public void Raise(){   t++;  }  public int GetTimes(){   return t;  } } class Test{  public static void main(String[] arg){   Hand rHand=new Hand();   Hand lHand=new Hand();   rHand.Raise();   rHand.Raise();   lHand.Raise();   Raise2(lHand);   System.out.println("Right hand has raised "+rHand.GetTimes()+" times);   System.out.println("Left hand has raised "+lHand.GetTimes()+" times);   //Hand dummy=rHand;   //System.out.println("dummy "+dummy.GetTimes()+ "times); //エラー  }  public static void Raise2(Hand h){   h.Raise();   h.Raise();  } } dummy.GetTimes()のところでシンボルを解決出来ないというコンパイルエラーでした。 こういうのもダメなんですかねぇ > 逆に言うと、Cで書けていることをあえて、なぜJavaで書き換えるのですか、 質問者さんが何のために移植しようとされているのかは知りませんが、 たとえばWrite Once, Run Anywhereは移植の理由にはなりませんか?

kahata
質問者

補足

> 逆に言うと、Cで書けていることをあえて、なぜJavaで書き換えるのですか、 一つの理由はCで動いているある便利なプログラムをWebに載せるためですが、そこまで問い質さなくても単純な技術的質問と考えて頂いて結構です。 私の場合スタンドアロンのプログラミングはC/C++、ウエブはPHPで殆ど事足りており、JaVAを使うのはよほど特殊なケースでJAVAにあまり慣れていません。

  • _ranco_
  • ベストアンサー率58% (126/214)
回答No.11

要するに、アプリケーションのレベルでの要求が、質問からはよーわからんから、Java的な良いお答えを書きようがない。 いちばんまともなのは、オブジェクトを作るか入手して、そのオブジェクトのpublicメソッドを呼ぶことです。staticメソッドなら、オブジェクトではなくpublicなクラス。

  • bgbg
  • ベストアンサー率53% (94/175)
回答No.10

Class#getMethod で当該のメソッドを取得し、Method#invoke で実行します。 以下サンプル。printlnを使った例。 import java.io.PrintStream; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; public class QA3787147 { public static void main( String[] args ) { PrintStream out = System.out; try { // printlnメソッドのオブジェクト取得 Method aMethod = System.out.getClass().getMethod( "println", String.class ); // 引数の用意 Object[] arg = {"Hello world!"}; // 実行する。 aMethod.invoke( out, arg ); } catch ( SecurityException e ) { e.printStackTrace(); } catch ( NoSuchMethodException e ) { e.printStackTrace(); } catch ( IllegalArgumentException e ) { e.printStackTrace(); } catch ( IllegalAccessException e ) { e.printStackTrace(); } catch ( InvocationTargetException e ) { e.printStackTrace(); } } } Javaでの動的メソッドの取得実行(クラスも変数も同じような方法でできますが)は重いし面倒だしJavaの持つ強力な型チェック機能も台無しなので、平素な代替手段があるならそちらを使ったほうが良いです。

kahata
質問者

お礼

専門家らしいご回答をどうもありがとうございます。色々勉強させて頂きます。

noname#119918
noname#119918
回答No.9

詳しく調べていないのですが、 ClassクラスのgetMethodメソッドを使うと良さそうです。

  • koko_u_
  • ベストアンサー率18% (459/2509)
回答No.8

なんだか C 言語エライ貶されてますが、使われなくなった古代言語でもないし、その手法はまだまだ健在です。 まあ、古くからある言語なので、当時は「処理をブロックとして渡す」ための実装方法が関数ポインタだったわけですわ。 Java は Java の流儀に従ってコーディングすればいいんだけど、質問者さんの「C ではこう書いていたけど、Java ではどうするんだろう」っていう疑問が悪いとは思いませんよ。

kahata
質問者

補足

エライ所に議論が行っていますが・・・Cを古代言語、死語として卑下するのは多少引っかかります。アセンブラやCOBOLと比較している訳じゃないしJAVAと同じALGOL系で英語とフランス語のような関係です。またC→C++→C#と発展していますのでオブジェクト指向やポインタの議論は当らないと思います。何より重要なのはUNIX,Windows等多くのOSのベース言語であり色々な各種言語(compiler)がC/C++で書かれている事です。ただ、ウエブアプリケーションの開発に向かないのは確かですが。。。

  • dyna_1550
  • ベストアンサー率34% (122/353)
回答No.7

質問者様に申し訳ないのですが、_ranco_さんに賛同します。 Javaは比較的オブジェクト指向を強く意識した言語と思いますので、 処理を外部に委託しようとする関数ポインタはなじまないと 考えるのが筋と思います。(個人的な意見としてです) デザインパターンの臭いがプンプンするJavaなので、Javaでの解決方法として 「○○パターンに書き換える」、という議論の方が本質と思います。 逆に言うと、Cで書けていることをあえて、なぜJavaで書き換えるのですか、 ということになると思います。

  • _ranco_
  • ベストアンサー率58% (126/214)
回答No.6

> 言語を比較しながら学ぶことは 多くの場合、古代言語との比較は、「現行の刑法で切腹と同等の刑を与える方法を教えてください」などの議論と同じで、最初からナンセンスです。 Methodクラス、CallableとFutureクラス、などを実際に小さなプログラムを書きながら勉強してみてください。

  • _ranco_
  • ベストアンサー率58% (126/214)
回答No.5

そんなことより、アプリケーションのレベルの要求をJavaと照らしてよく見据えるべきです。関数ポインタなどより、もっと安全で堅牢な方法があるはず。私はC(などの古代言語)のナニナニをJavaで書くには?という話題が大嫌いです。真剣な開発にとって、無意味かつ無メリットだから。

kahata
質問者

補足

専門家らしい人からこんなことを言われると身も蓋もなくなります。初心者にとって言語を比較しながら学ぶことは、その言語の理解を深める上で当然あってよい手法です。

関連するQ&A