質問

質問者:kahata 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;
}
質問投稿日時:08/02/18 15:00
質問番号:3787147
この質問に対する回答は締め切られました。
最新から表示回答順に表示良回答のみ表示

回答

 

回答者:SAYKA 「参照渡し」で調べたら出るんじゃないかな
http://www.google.co.jp/search?q=java%E3%81%A7%E5%8F%82%E7%85%A7%E6...
種類:アドバイス
どんな人:一般人
自信:参考意見
回答日時:08/02/18 15:12
回答番号:No.1
この回答へのお礼この回答にお礼をつける(質問者のみ)

回答

 

回答者:taloo callback関数の渡す方法があるようですが、これで行けないでしょうか。
未検証です。

// 型がわかりません
private myClass.func po=new myClass.func();
i= po(10, 3);

class myClass{
//finalって必要?
 public final int func(int a, int b){
  return a+b;
 }
}


JAVAはまだ素人ですが、
ifを省略するために配列にしたりすることが多いので、JAVAでもこういう方法が使えるといいですけどね。
if(a==0){
func0();
}else if(a==1){
func1();
}else if(a==2){
func2();
}

// funcs[0]=new func0();
// funcs[1]=new func1();
// funcs[2]=new func2();
a=0;
funcs[a](); //ifを省略して実行
種類:アドバイス
どんな人:一般人
自信:参考意見
回答日時:08/02/18 17:28
回答番号:No.2
参考URL: http://mindprod.com/jgloss/callback.html
この回答へのお礼この回答にお礼をつける(質問者のみ)

回答

 

回答者:koko_u_ Java には関数オブジェクトってないみたいね。
JDK7 の仕様には入るみたい
http://journal.mycom.co.jp/articles/2006/08/23/java7closuer/index.html

それまでは自前で適当に関数のように動作するクラスを作るしかないのでは?
種類:アドバイス
どんな人:一般人
自信:参考意見
回答日時:08/02/18 17:52
回答番号:No.3
この回答へのお礼この回答にお礼をつける(質問者のみ)

回答

良回答20pt

回答者:Gishi こんな感じでしょうか。

  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();
のような形になります。
種類:回答
どんな人:経験者
自信:自信あり
回答日時:08/02/18 18:00
回答番号:No.4
この回答へのお礼完璧な回答をありがとうございました。test proofです。
もうひとつ、別の質問になるかも知れないのですが、javaでphpの
call_user_func_array()のようなことができればよいのですが・・・
つまり、関数名をstringで与えて動的に関数を呼び出す方法です。

回答

 

回答者:_ranco_ そんなことより、アプリケーションのレベルの要求をJavaと照らしてよく見据えるべきです。関数ポインタなどより、もっと安全で堅牢な方法があるはず。私はC(などの古代言語)のナニナニをJavaで書くには?という話題が大嫌いです。真剣な開発にとって、無意味かつ無メリットだから。
種類:回答
どんな人:専門家
自信:自信あり
回答日時:08/02/18 19:02
回答番号:No.5
この回答への補足専門家らしい人からこんなことを言われると身も蓋もなくなります。初心者にとって言語を比較しながら学ぶことは、その言語の理解を深める上で当然あってよい手法です。
この回答へのお礼この回答にお礼をつける(質問者のみ)

回答

 

回答者:_ranco_ > 言語を比較しながら学ぶことは
多くの場合、古代言語との比較は、「現行の刑法で切腹と同等の刑を与える方法を教えてください」などの議論と同じで、最初からナンセンスです。

Methodクラス、CallableとFutureクラス、などを実際に小さなプログラムを書きながら勉強してみてください。
種類:アドバイス
どんな人:専門家
自信:自信あり
回答日時:08/02/18 20:24
回答番号:No.6
この回答へのお礼この回答にお礼をつける(質問者のみ)

回答

 

回答者:dyna_1550 質問者様に申し訳ないのですが、_ranco_さんに賛同します。

Javaは比較的オブジェクト指向を強く意識した言語と思いますので、
処理を外部に委託しようとする関数ポインタはなじまないと
考えるのが筋と思います。(個人的な意見としてです)

デザインパターンの臭いがプンプンするJavaなので、Javaでの解決方法として
「○○パターンに書き換える」、という議論の方が本質と思います。

逆に言うと、Cで書けていることをあえて、なぜJavaで書き換えるのですか、
ということになると思います。
種類:アドバイス
どんな人:一般人
自信:参考意見
回答日時:08/02/18 23:42
回答番号:No.7
この回答へのお礼この回答にお礼をつける(質問者のみ)

回答

 

回答者:koko_u_ なんだか C 言語エライ貶されてますが、使われなくなった古代言語でもないし、その手法はまだまだ健在です。

まあ、古くからある言語なので、当時は「処理をブロックとして渡す」ための実装方法が関数ポインタだったわけですわ。
Java は Java の流儀に従ってコーディングすればいいんだけど、質問者さんの「C ではこう書いていたけど、Java ではどうするんだろう」っていう疑問が悪いとは思いませんよ。
種類:アドバイス
どんな人:一般人
自信:参考意見
回答日時:08/02/19 00:24
回答番号:No.8
この回答への補足エライ所に議論が行っていますが・・・Cを古代言語、死語として卑下するのは多少引っかかります。アセンブラやCOBOLと比較している訳じゃないしJAVAと同じALGOL系で英語とフランス語のような関係です。またC→C++→C#と発展していますのでオブジェクト指向やポインタの議論は当らないと思います。何より重要なのはUNIX,Windows等多くのOSのベース言語であり色々な各種言語(compiler)がC/C++で書かれている事です。ただ、ウエブアプリケーションの開発に向かないのは確かですが。。。
この回答へのお礼この回答にお礼をつける(質問者のみ)

回答

 

回答者:HKB 詳しく調べていないのですが、
ClassクラスのgetMethodメソッドを使うと良さそうです。
種類:アドバイス
どんな人:経験者
自信:参考意見
回答日時:08/02/19 07:48
回答番号:No.9
この回答へのお礼この回答にお礼をつける(質問者のみ)

回答

良回答10pt

回答者:bgbg 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の持つ強力な型チェック機能も台無しなので、平素な代替手段があるならそちらを使ったほうが良いです。
種類:回答
どんな人:専門家
自信:参考意見
回答日時:08/02/19 09:59
回答番号:No.10
この回答へのお礼専門家らしいご回答をどうもありがとうございます。色々勉強させて頂きます。

回答

 

回答者:_ranco_ 要するに、アプリケーションのレベルでの要求が、質問からはよーわからんから、Java的な良いお答えを書きようがない。

いちばんまともなのは、オブジェクトを作るか入手して、そのオブジェクトのpublicメソッドを呼ぶことです。staticメソッドなら、オブジェクトではなくpublicなクラス。
種類:補足要求
どんな人:専門家
自信:参考意見
回答日時:08/02/19 11:46
回答番号:No.11
この回答へのお礼この回答にお礼をつける(質問者のみ)

回答

 

回答者:taloo 質問に対する回答じゃなくてすみませんが。

> 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は移植の理由にはなりませんか?
種類:アドバイス
どんな人:一般人
自信:参考意見
回答日時:08/02/20 04:03
回答番号:No.12
この回答への補足> 逆に言うと、Cで書けていることをあえて、なぜJavaで書き換えるのですか、
一つの理由はCで動いているある便利なプログラムをWebに載せるためですが、そこまで問い質さなくても単純な技術的質問と考えて頂いて結構です。
私の場合スタンドアロンのプログラミングはC/C++、ウエブはPHPで殆ど事足りており、JaVAを使うのはよほど特殊なケースでJAVAにあまり慣れていません。
この回答へのお礼この回答にお礼をつける(質問者のみ)

回答

 

回答者:taloo 連続失礼。
> dummy.GetTimes()のところでシンボルを解決出来ないというコンパイルエラーでした。
エラーの原因はtypoでした○| ̄|_
種類:アドバイス
どんな人:一般人
自信:参考意見
回答日時:08/02/20 04:06
回答番号:No.13
この回答へのお礼この回答にお礼をつける(質問者のみ)

回答

 

回答者:choconamacream /**
取り敢えずは、動くのを作ってみた。(但し、入力チェックは省略。)
ご参考までに・・・。

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」で。");
  }

 }
}
種類:回答
どんな人:経験者
自信:自信あり
回答日時:08/02/20 23:34
回答番号:No.14
この回答へのお礼call_user_func_array()の件は余談のつもりでしたのに丁寧にフォローして頂きありがとうございます、面白いです。大変有用で参考になります。
最新から表示回答順に表示良回答のみ表示