弁証法的変数とは何ですか?
誰かが言うかもしれない:「哲学とプログラミングの共通点は?」 近視眼の人は「何もありません!」と言うでしょう、そして私たちはそれについて考えます。
哲学のそのような分岐があります-弁証法。 弁証法の3つの法則が策定されました。
1.量的変化から質的変化への移行の法則
2.統一の法則と対立の闘い
3.否定の否定の法則
最初の法則の定義から、弁証法的変数の概念が生まれました。
弁証法的変数は、オブジェクトの特定のプロパティであり、その値は、オブジェクトの内部状態
、特定のクラスに属するオブジェクト
、および結果としての動作を決定します。 たとえば、温度は水と氷のクラスの弁証法的変数であり、子供と成熟したクラスの年齢などです。
この記事では、hegel4j弁証法変数を操作するためのライブラリを説明し、このライブラリを操作する例を示します。
Hegel4jの概要
Hegel4jは、方言変数を記述することができるJavaライブラリです。 このような変数を宣言するには、特定のクラスのフィールドの前に
@Dialecticアノテーションを宣言する必要があります。 たとえば、次のように:
public class Water{
@Dialectic(expr="<0",target=Ice. class )
private float tempetarute;
...
}
* This source code was highlighted with Source Code Highlighter .
上記の例では、Waterクラスの弁証法的変数温度について説明しています。
注釈の最初のパラメーターは
exprです。これは、変換をいつ実行するかを決定する式です。 式の形式は、<relation> <value>です。 リレーションは、比較演算の1つです。<、<=、== 、! =、>、> =。 値は整数値または実数です。 変数の値が式の左側にあることが暗示されます。 式の例を次に示します。「> 100」、「!= 7」、「> 3.1415」、「<= 2.61」。
注釈の2番目のパラメーターは
ターゲットです -条件が満たされた場合、このオブジェクトはこのクラスのオブジェクトのように動作する必要があることを示すように。
3番目のパラメーターもあります:
トランスフォーマー -このパラメーターは、オブジェクトの変換を担当する変換クラスを設定します。 デフォルトでは、値はSimpleObjectTransformerです。 ただし、「トランスフォーマー」を実装する場合は問題ありません
。ObjectTransformerインターフェースを実装し、結果のクラスをパラメーターとしてアノテーションに渡すだけです。
どのように機能しますか?
現時点では、ライブラリの実装にはいくつかの欠点がないわけではないため、まず第一に、このライブラリを使用する人に、そのライブラリがどのように構成されているかを想像してもらいたいです。 いずれにしても、Habrコミュニティは、ライブラリが内部からどのように配置されているかを見ることに興味があると思います。
まず、ライブラリの現在のバージョンでは、クラスがJavaBeans仕様に従って記述されていると想定されていることに注意してください。つまり、各変数xにはsetX()およびgetX()メソッドがあります。 したがって、他のメソッドで変数の値が変更されても、オブジェクトはそのクラスと状態を変更しません。
次に、オブジェクトの動作がどのように実装されるかを検討します。 すべての魔法はアスペクト(アスペクト指向プログラミングを参照)で始まり、デザイナーの呼び出しを(現時点ではほとんどすべて)インターセプトし、このクラスに弁証法的変数があるかどうかを分析します。 クラスに弁証法変数が含まれる場合、プロキシオブジェクトが作成され、プロキシがコンストラクタの呼び出しコンテキストに返されますが、プロキシは元のクラスのオブジェクトのように動作します。
プロキシを作成すると、MethodInterceptorがパラメーターとして設定されます。これは、プロキシオブジェクトメソッドを呼び出すためのインターセプターです。 そして、このインターセプターの内部には、呼び出しが転送される実際のオブジェクトが既にあります。
使い方は?
このライブラリは、1.6以上のJavaバージョンで動作します。
このライブラリの機能を使用するには、このライブラリをjavaビルドパスとAspectJビルドパスに追加する必要があります。
また、作業には次のライブラリが必要です。
cglib-nodepアスペクトこのライブラリを使用した例を実例として示します。
IOrderインターフェースがあるとしましょう:
public interface IOrder {
public long getPrice();
public void setPrice( long price);
public String getOrderType();
public long getTotal();
}
* This source code was highlighted with Source Code Highlighter .
getTotal()メソッドに注意してください。これは最終的な注文値を返します。
Orderクラスもあります。
public class Order implements IOrder{
@Dialectic(expr= ">=1000" ,target=VIPOrder. class )
private long price;
public long getPrice() {
return price;
}
public void setPrice( long price) {
this .price = price;
}
public Order( long price) {
super();
this .price = price;
}
public String getOrderType(){
return "simple order" ;
}
public long getTotal(){
return price;
}
}
* This source code was highlighted with Source Code Highlighter .
また、1000 cu以上を注文すると15%割引になるVIPOrderもあります。
public class VIPOrder implements IOrder
{
@Dialectic(expr= "<1000" ,target=Order. class )
private long price;
public long getPrice() {
return price;
}
public void setPrice( long price) {
this .price = price;
}
public VIPOrder( long price) {
super();
this .price = price;
}
public String getOrderType(){
return "VIP order" ;
}
@Override
public long getTotal() {
return Double.valueOf(price*0.85).longValue();
}
}
* This source code was highlighted with Source Code Highlighter .
次に、注文で別の価格を指定した場合に何が起こるかを見てみましょう。
public class Main {
/**
* @param args
*/
public static void main( String [] args) {
Order order = new Order(154);
System. out .println( "" +order.getOrderType()+ " total " +order.getTotal());
order.setPrice(1200);
System. out .println( "" +order.getOrderType()+ " total " +order.getTotal());
order.setPrice(504);
System. out .println( "" +order.getOrderType()+ " total " +order.getTotal());
}
}
* This source code was highlighted with Source Code Highlighter .
アプリケーションを起動すると、価格フィールドの値に応じて最終価格が異なる方法で計算され、実際、Orderクラスのオブジェクトが作成され、オブジェクトへの参照が変更されていないにもかかわらず、異なるクラスのメソッドが呼び出されることがわかります:
simple order total 154
VIP order total 1020
simple order total 504
ここで2つの変換が行われたことに注意してください:最初は154 cuの量で通常の注文があり、それがVIP注文になり、最終価格が値引きされたことが判明しました。
これは何のためですか?
おそらくご存知のように、OOPには3つの柱があります。ポリモーフィズム、カプセル化、継承です。 ただし、実際のアプリケーションを見ると、ポリモーフィズムがそれほど頻繁に使用されていないことがわかります。 その理由の1つは、クラスに弁証法変数がある場合、オブジェクトを他のクラスに変換するロジックを記述したくない場合があることです。アプリケーションがまだ小さい場合は、メソッド内に動作ロジックを構築する方がはるかに簡単です。 たとえば、次のように:
getTotal(){
if (price>=1000){
return price*0.85;
} else {
return price;
}
}
* This source code was highlighted with Source Code Highlighter .
ただし、多態的なメソッドが多いほど、アプリケーションロジックを制御するのが難しくなります。 したがって、このような場合、ポリモーフィズムを使用することをお勧めします。 また、変数の値を追跡してオブジェクトを変換するロジックを作成するという重い負担をプログラマの肩から取り除くために、このライブラリが作成されました。
結論として
あなたの意見や提案を聞きたいです。 近い将来の計画では、JSON( "<{id =" 123 "、name =" sd "}")および "<sin(90)/4.3"などの複雑な式を使用する式で、任意のタイプのオブジェクトのサポートが追加されます。パフォーマンスを改善します。
ここで実際のライブラリをダウンロードして試すことができます。