プロが教えるわが家の防犯対策術!

C#のデリゲードを
javaとC++でできないでしょうか。

ただし、質問内容を勘違いされそうなので、求めている内容と、
求めていない内容を、詳しく
書きますと。


インタフェース委譲を使った例は、求めていません。
あらかじめ、委譲先に静的に仕組みを
作っておかなく手も、C#のデリゲードのように、シグニチァが同じなら
委譲先をはめ込めれるのが欲しいです。


単なる関数ポインタの例は、求めて
いません。
C#でdelegate型を引数にとる
ところに、あるインスタンスの
メソッドを渡すと。
どのインスタンスのどのメソッドかまで、
認識して、コールバックできます。
関数ポインタでは、これができない。


STLの関数オブジェクトとか、古い感じの情報にヒントがあるか。調べてみましたが。よくわかりませんでした。
結局、この関数オブジェクトは、僕が求めているモノとは、違うような気がします。
よくわかりませんが。

欲しいのは、どのインスタンスのどのメソッドかまでを特定して、
記憶できる型をどうやって
javaや、C++で実装できるか。
それをインタフェース委譲のように、
委譲先にあらかじめ、仕込んでおくことなしに。
ただ、メソッドのシグニチァが同じであるだけで、どのインスタンスのどのメソッドかまでを特定して記憶できる
C#のデリゲードのような型を。

特殊なコンポーネントを利用せず。

標準的な言語構文のみをつかって、
どのようにしたら、
javaや、C++で、実装できるか?
です。

詳しい方が、いらっしゃいましたら、
教えてください。

A 回答 (4件)

> [&obj1](int x, int y){ return obj1.add(x,y);}は、


> 新たに、ラムダ式のようなものを作って、
> delgに指定してるようにみえるです

"ようなもの"じゃなく、これがC++のラムダ式です。

> obj1のaddを直で、取得し、その上記の型の変数や引数で
> 受けることは。
> C++の標準的な構文では、不可能なのでしょうか?

直接取得するのは無理。あえてやるなら
#include <iostream>
#include <functional>

using namespace std;

class foo {
int base;
public:
explicit foo(int b) : base(b) {}
int add(int x, int y) const { return base + x + y; }
// ↓ラムダ式を返すメソッド
function<int(int,int)> add_delg() const { return [this](int x, int y) { return add(x,y); }; }
};

int main() {
function<int(int,int)> delg; // delegate int delg(int,int)
foo obj1(1);
foo obj2(2);

delg = obj1.add_delg();
cout << delg(2,3) << endl;
delg = obj2.add_delg();
cout << delg(2,3) << endl;
}

この回答への補足

素晴らしいです。
なんでもできるんですね。
天才的な人だ。
add_delg
みたいなのが、まさに、それ。

C#の場合は、メソッドそのものが、
直でdelegateに指定できて、
メソッドそのものが、もう
デリゲードそのもののように
見えるんですが。

C++では、
ラムダ式の形をとらないと。
『どのインスタンス』か?
という情報をもったものを
取得する手段がないということですか。

[this]という構文が
このインスタンスです、といって、
そのロジックが、
(int x,int y) { return add(x,y);}
ですといってようです。

昔、メンバー関数を、関数ポインタに
指定しようとして、
コンパイラに怒られて、
あぁ、無理なのか。
そういえば、メンバー関数は
どのインスタンスか?
という情報もあるし。
別物なんだろなと、
思ってたです。
メンバー関数に、直でコールバックするのってどうするんだろ。
って、おもったまま、
今回の回答をもらうまで、
ずっと、わからなかったです。 

functin<int(int,int)>
中身がどうなってるか
不思議だけど、
勉強になったです。

補足日時:2014/12/16 01:54
    • good
    • 0

Javaだと以下のような記述になると思います。



例:C#

MyClass instance = ...
delegate int Foo(int a, int b);
Foo d = new Foo(instance.method);
int result = d(1, 2);

例: Java(Java8以降)

import java.util.function.BiFunction

MyClass instance = ...
BiFunction<Integer, Integer, Integer> d = (a, b) -> instance.method(a, b);
int result = d.apply(1, 2);

なお引数の個数が0~2の場合はjava.util.functionパッケージの定義済みインターフェースを利用できますが、個数が3つ以上のものは個数毎に個別のインターフェースを自前のライブラリーなどに定義することになります。

この回答への補足

ありがとうごさいます。
No.2のC++の回答も、
No.3のjavaの回答も、
ラムダ式的なもので、
このインスタンスのこのメソッドを
呼ぶようなコードを書いて。

それをfunctin的なシグニチァと戻り型だけを定義した型で受けて
コールバックする感じのようですね。
これだと、この受けてる型自体には、
どのインスタンなのかという情報ないですが、ラムダ式の実装で、どのインスタンスのどのメソッドかをかけば。
実際問題、不便ではない。
どうせ、C#でも、そのデリートに
値を指定する部分で、
obj.addというのを書いて。
このインスタンスのこのメソッドを
渡すとかくのだから。。

C#のデリートが特殊で
No.2, 3のほうが実は標準的な感じに
みえたです。
C#のデリートが、すごく便利なので、
おんなじこと、できんだろか。
前々から、思ってたので、勉強になったです。

javaも8は、ラムダ式かけるんですね
これも、知りませんでした。


No.2の最後で回答の補足で、
した欲張った質問は、
ちょっと、ムリそうな感じではと
思われるです。

僕は、ちょっと、勉強が足りないです。
BiFunctinの中身のソースコードが
どうなってるか想像つかない。

ラムダ式ようなものを、C#のデリート以外の方法で受ける手段としての
インタフェースを定義
できるということすらわかってなかったです。

3つ以上の引数バージョンのインタフェースの実装の想像がつかない。
でも、無知な部分が何かが、
浮き彫りになって、
とても、意味があったです。

補足日時:2014/12/14 17:13
    • good
    • 0

> aのfooと、bのbarにそれぞれきちんと


> 区別してコールバックできるのでしょうか。

#include <iostream>
#include <functional>

using namespace std;

class foo {
int base;
public:
explicit foo(int b) : base(b) {}
int add(int x, int y) { return base + x + y; }
};

int main() {
function<int(int,int)> delg; // delegate int delg(int,int)
foo obj1(1);
foo obj2(2);

delg = [&obj1](int x, int y) { return obj1.add(x,y); };
cout << delg(2,3) << endl;
delg = [&obj2](int x, int y) { return obj2.add(x,y); };
cout << delg(2,3) << endl;
}

> function<int,int>は、なぜ、
> intを返すのでしょうか?

function<int,int> ではありません、function<int(int,int)> です。

この回答への補足

さっそく、ありがとうごさいます。
こんな質問にまともに、回答できるとは、
おそらく、スゴ腕な人ではないかと
思うです。

基本的なことを確認したいのですが。
&obj1がobjのアドレスでしょうか。
この場合の[ ]の記号は
どういう意味をもっているのでしょうか?

それで、
[&obj1](int x, int y){ return obj1.add(x,y);}
は、
新たに、ラムダ式のようなものを
作って、
delgに指定してるようにみえるです

この方法だと、大枠、求めてるものに
近く見えるです。
確かに、obj1のaddと、obj2のaddを
うまく呼びわけてるです。
すごいです。

欲張ったように質問して
すいませんが。

特定のインスタンスの特定メソッドを
表すオブジェクトの型、
つまり、C#のデリートに
そっくりな型を実装し、

obj1のaddを直で、取得し、
その上記の型の変数や引数で
受けることは。

C++の標準的な構文では、不可能なのでしょうか?

補足日時:2014/12/14 15:38
    • good
    • 0

#include <iostream>


#include <functional>

using namespace std;

int main() {
function<int(int,int)> delg; // delegate int delg(int,int)
delg = [](int x, int y) -> int { return x+y; }; // x,y => x+y
//delg = [](int x, int y) -> char* { return (char*)"hello"; }; // error
cout << delg(2,3) << endl;
}

こんなのですか?
# Javaはわからんです

この回答への補足

さっそく、ありがとうごさいます。
普通の関数ポインタのような
使い方のように見えますが。

function<int,int>が
僕には詳しくわからないのですが。

private method(function<int, int> argcallback) {
int ret = argcallback(2,3);
return ret;
}

というものにたいして、

intを2つ引数にとりintを返すfooメソッドを持つ型のインスタンスaと、
intを2つ引数にとりintを返すbarメソッドを持つ型のインスタンスbとがあり、
a, bが異なる型であったとします。

このとき。
method(a.foo);
method(b.bar);
と書いた時、
aのfoo
と、bのbarにそれぞれきちんと
区別してコールバックできるのでしょうか。
僕が求めているのは、そこで、
どのインスタンスのどのメソッドかを記憶できるか?という点

補足で、質問あるですが。
function<int,int>は、なぜ、
intを返すのでしょうか?
delegate int delg(int,int)
が、コメントでかいてありましたので。

補足日時:2014/12/14 11:59
    • good
    • 0
この回答へのお礼

もう少し、わかりやすく、
求めている内容を補足すると。
C#のデリートのように、
インスタンスのメソッド(メンバー関数)
を指定できるか。という点。

単なる関数ポインタのように、
どのクラスにも、属さない
グローバルな位置にある関数を
受けれる

とか、クラスに属していても、
特定のインスタンスにひもづいていない、
staticな関数を受けれる

とか、そういうのではなく、

ある特定のインスタンスのメソッド(メンバー関数)を受けれて。

そのインスタンスのそのメソッドへコールバックするようにできないか?
ということです。
インスタンスは、その時の状態をもっているので、それぞれのインスタンスを区別して指定したメソッドへコールバックしたいのです。

そして、その時、できれば。
(可能であればですが。)
#include <functional>

のように、環境によっては、利用できないかもしれないものをできるだけ利用せず、
言語が持ってる標準的な構文だけで、
C#のデリート型のような型を実装する方法が、あれば。

そこを求めています。

お礼日時:2014/12/14 12:29

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