私は現在、クライアント、ビジネス、製品などのオブジェクトを表す多くのクラスを備えたシステムを実装しています。標準的なビジネスロジック。当然のことながら、各クラスには多数の標準属性があります。
次のような本質的に同一の要件の長いリストがあります。
- 産業が製造業であるすべてのビジネスを検索する機能。
- ロンドンに拠点を置くすべてのクライアントを取得する機能
クラス ビジネスには属性セクターがあり、クライアントには属性ロケーションがあります。明らかにこれはリレーショナルの問題であり、疑似 SQL では次のようになります。
SELECT ALL business in business' WHERE sector == manufacturing
残念ながら、DB へのプラグインはオプションではありません。
私がやりたいことは、署名が次の形式をとる単一の汎用集計関数を持つことです。
vector<generic> genericAggregation(class, attribute, value);
class は集約したいオブジェクトのクラスであり、attribute と value は対象のクラス属性と値です。私の例では、ベクトルを戻り値の型として入れましたが、これはうまくいきません。おそらく、関連するクラス型のベクトルを宣言し、それを引数として渡す方がよいでしょう。しかし、これは主な問題ではありません。
クラス、属性、および値の文字列形式で引数を受け取り、これらを汎用オブジェクト集約関数にマップするにはどうすればよいですか?
コードを投稿しないのは失礼なので、以下は想像力に富んだ名前のクラスのオブジェクトの束を作成するダミー プログラムです。含まれているのは、コマンド ラインで指定された ID と等しい A オブジェクトを持つ B オブジェクトのベクトルを返す特定の集計関数です。
$ ./aggregations 5
これは、A オブジェクトの 'i' 属性が 5 に等しいすべての B を返します。以下を参照してください。
#include <iostream>
#include <cstring>
#include <sstream>
#include <vector>
using namespace std;
//First imaginativly names dummy class
class A {
private:
int i;
double d;
string s;
public:
A(){}
A(int i, double d, string s) {
this->i = i;
this->d = d;
this->s = s;
}
~A(){}
int getInt() {return i;}
double getDouble() {return d;}
string getString() {return s;}
};
//second imaginativly named dummy class
class B {
private:
int i;
double d;
string s;
A *a;
public:
B(int i, double d, string s, A *a) {
this->i = i;
this->d = d;
this->s = s;
this->a = a;
}
~B(){}
int getInt() {return i;}
double getDouble() {return d;}
string getString() {return s;}
A* getA() {return a;}
};
//Containers for dummy class objects
vector<A> a_vec (10);
vector<B> b_vec;//100
//Util function, not important..
string int2string(int number) {
stringstream ss;
ss << number;
return ss.str();
}
//Example function that returns a new vector containing on B objects
//whose A object i attribute is equal to 'id'
vector<B> getBbyA(int id) {
vector<B> result;
for(int i = 0; i < b_vec.size(); i++) {
if(b_vec.at(i).getA()->getInt() == id) {
result.push_back(b_vec.at(i));
}
}
return result;
}
int main(int argc, char** argv) {
//Create some A's and B's, each B has an A...
//Each of the 10 A's are associated with 10 B's.
for(int i = 0; i < 10; ++i) {
A a(i, (double)i, int2string(i));
a_vec.at(i) = a;
for(int j = 0; j < 10; j++) {
B b((i * 10) + j, (double)j, int2string(i), &a_vec.at(i));
b_vec.push_back(b);
}
}
//Got some objects so lets do some aggregation
//Call example aggregation function to return all B objects
//whose A object has i attribute equal to argv[1]
vector<B> result = getBbyA(atoi(argv[1]));
//If some B's were found print them, else don't...
if(result.size() != 0) {
for(int i = 0; i < result.size(); i++) {
cout << result.at(i).getInt() << " " << result.at(i).getA()->getInt() << endl;
}
}
else {
cout << "No B's had A's with attribute i equal to " << argv[1] << endl;
}
return 0;
}
コンパイル:
g++ -o aggregations aggregations.cpp
ご希望の場合 :)
別の集計関数 (つまり、例では getBbyA() ) を実装する代わりに、すべての集計要件が満たされるように、すべての可能なクラス属性ペアを説明する単一の汎用集計関数が必要です..そしてイベントでは追加の属性後で追加される場合、または追加の集計要件がある場合、これらは自動的に考慮されます。
ここにはいくつかの問題がありますが、私が洞察を求めている主な問題は、ランタイム引数をクラス属性にマップする方法です。
私がやろうとしていることを適切に説明するのに十分な詳細を提供できたことを願っています...