2016-05-28 4 views
1

小さなゲームを開発しているときに、私は昨夜自分自身で問題をコード化しました。先日、私は余暇の時間を何か生産的なものに費やすべきだと自分に確信していました。ゲームの代わりに、テキストベースのRPGで作業を始めることに決めました。私は、その後、ゲームで通貨を表す問題に来ました。さて、これはちょうど楽しみのためであるので、私は少し自分に挑戦したいと思います。 1つの値として通貨を表すだけではなく(例えば、「金貨」と呼ばれる1種類のコインがゲーム内の唯一のコインではありません)。さまざまな通貨を表すための静的クラスの使用

4種類のコイン - ペンス、銅、デンタル、オレン。硬貨の4つすべては、重量、体積、材料、および名前などの値を有する。さらに、コインには相対的な価値を決定する為替レートがあります。この点は、さもなければ退屈な古い通貨とは異なるものを許すことでした。私の問題は、その実装方法がわからないことです。

私が最後の夜に到着したのは、抽象クラスのCoinを拡張する4つのクラス(Pence、Copper、Denar、Oren)でした。コインには、4つのサブクラスすべてに対して、DENSITY、VOLUME、NAME、EXCHANGEなどの多くの保護された静的要素が含まれています。

サブクラスのコンストラクタは次のようになります。

public Coppers() { 
    super(); 
    super.metal = COPPER_METAL; 
    super.name = COPPER; 
    super.setVolume(); 
    super.setDensity(); 
    super.setWeight(); 
} 

そして、このようなスーパークラスの外観のメソッド:

protected void setDensity() { 
    switch(getMetal()) { 
    case "copper": 
     this.density = DENSITY_COPPER; 
     break; 
    case "silver": 
     this.density = DENSITY_SILVER; 
     break; 
    case "gold": 
     this.density = DENSITY_GOLD; 
     break; 
    default: 
     this.density = DENSITY_COPPER; 
     break; 
    }; 
} 

これはひどく...間違っているようです。私はベストプラクティスが何であるかはわかりません。私は静的なクラスを使ってこれらの値を保持することについて友達に尋ね、混在した応答を受けました。しかし、これらのクラスのPOINTは重要です。プレイヤークラスに、さまざまなタイプのコインの数を追跡する、「財布」と呼ばれるオブジェクトがあるとします。彼らの財布で、プレーヤーは銀行でコインを交換し、商品を購入し、コインのために商品を売ることができます。インスタンス化されたすべてのコインのセットを保持することは意味がありません。私はちょうど情報と方法が必要です。静的クラスの実装は意味があるのでしょうか?どのようにして4つの硬貨がすべて非常に多くの物件を共有しているときに最高の状態になるのですか?

+0

[Javaの列挙]を見(https://docs.oracle.com/javase/tutorial/java/javaOO/enum:あなたはテストにそれを吸うために、このmainメソッドを使用することができます

public class CoinFactory { private CoinFactory() { } public static <T extends Coin> Optional<T> generateCoin(int weight, int volume, int density, Class<T> clazz) { Optional<T> coin = Optional.empty(); try { coin = Optional.of(clazz.getDeclaredConstructor(int.class, int.class, int.class) .newInstance(weight, volume, density)); } catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException e) { e.printStackTrace(); } return coin; } } 

.html)sは基本的にいくつかの構文的な砂糖を持つ静的なクラスです。 – markspace

+0

密度は変わりますか?なぜ金属のセッターでそれをセットするのではなく、重量と体積も同じです。なぜ保護されるのですか?プライベートはより良いアクセス修飾子になりませんか? – Natecat

+0

彼は正確なコインを持っているプレイヤーにとって重要です(100セントで1ドル/ユーロとは異なる状況になるでしょうか?もしそうでなければ、シンプルな 'int財布'を持っていて、ペニーを一杯にして、ビジュアルエクスペリエンスのためだけにこの数字をoren、denar、copperとpenniesに変換することができます。 –

答えて

0

濃度が「銅」、「金」、「銀色」で、DENSITY_の定数を持つ秘密のMapを「密度」に置き換えます(​​)。

this.density = densityMap.get(getMetal()); 

いっそ、スクラップsetDensity()、そして代わりに、単にdensityMap.get(getMetal())を返すgetDensity()を、持っている:setDensity()は単純に実行する必要があります。

+0

私は間違っていた。 Enumはより良い解決策ですが、私はsetDensityを持つことはおそらく不必要なセットアップのステップであるという考えに立っています。 –

1

この場合、あなたはEnumを使用します。必要な定数を列挙し、そのコンストラクタで型を与えます。

タイプがあるので、コード内で処理している文字列と比較できます。タイプが一致しない場合は、デフォルトでDensity.COPPERに設定されます。

Density density; 

protected void setDensity (String metal) { 
    for (Density d : Density.values()) { 
     if (metal.equals(d.getType())) { 
      this.density = d; 
      return; 
     } 
    } 
    this.density = Density.COPPER; 
} 

enum Density { 
    COPPER("copper"), 
    SILVER("silver"), 
    GOLD("gold"); 

    String type; 

    Density(String s) { 
     type = s; 
    } 

    public String getType() { 
     return type; 
    } 
} 
0

4種類のコインは動作が異なるので、1つのクラスで十分です。私は次のように提案します:

public enum Coin { 
    PENCE, COPPER, DENAR, OREN; 

    private static final String[] METAL = { "copper", "copper", "silver", "gold" }; 
    private static final int[] VALUE = { 1, 12, 60, 360 }; 

    public String getMetal() { 
    return METAL[ordinal()]; 
    } 

    public int getValue() { 
    return VALUE[ordinal()]; 
    } 
} 
+0

Enumsは私が一日中使うことを考えていたものでした。私は何かを鞭打ちして報告すると思う。 –

+0

この簡単な作業では、ほとんどの回答が不必要に複雑になります。 – eldo

1

ここでは逆に作業しましょう。

プレイヤークラスには、さまざまなタイプのコインの数を記録する「財布」というオブジェクトがあるとします。彼らの財布で、プレーヤーは銀行でコインを交換し、商品を購入し、コインのために商品を売ることができます。これが意味する何

public class Purse { 
    private final List<Coin> coins = new ArrayList<>(); 
} 

これは、列挙型は、ここで(十分に)十分ではないことを私に伝えます。このコンテキストでは、enumには複数の状態が記述されています。あなたが探しているのは、計算を行うために必要な値を保持できる実際のオブジェクトです。

この通貨を保持するつもりであれば、セントラルオブジェクトで説明しても間違いはありません。

私の考えでは、これに抽象クラスを使用するのはおそらく問題ありませんが、重要なコンポーネントが欠落しています。希望のタイプのコインを作成するファクトリです。コインの価値を知ることは大丈夫ですが、他のコインと比較してその価値がどのようなものであっても構いません。それはあなたの与えられたコインの価値に基づいていくつかの種類のコインを生産しようとするある種の交換目的の責任です。


これで、抽象クラスのコンストラクタを作成しましょう。ジェネリックコインを作ることを考えているなら、その量、密度、重量を知る必要があります。名前はそのクラス名によって提供されるので、あなたは本当にそれについて心配する必要はありません。後でそれを抽出することができます。

コイン階層の種類が必要な場合は、Comparableを利用できます。列挙する代わりに順序を述べる。

public abstract class Coin implements Comparable<Coin> { 

    protected final int volume; 
    protected final int density; 
    protected final int weight; 

    public Coin(int volume, int density, int weight) { 
     this.volume = volume; 
     this.density = density; 
     this.weight = weight; 
    } 

    public int getVolume() { 
     return volume; 
    } 

    public int getDensity() { 
     return density; 
    } 

    public int getWeight() { 
     return weight; 
    } 
} 

これは、ベアボーン​​タイプについて説明しています。

例として、Copperタイプもここで説明します。このコードは、同じタイプのコインが匹敵すると仮定します。それ以外の場合は、それを降格します(Copperはリストの最下部にあります)。

いくつかのことを守ってください。

  • 我々はcompareTo(私たちがしなければならないため)をオーバーライド
  • 親クラスからオリジナルのロジックの多くを保存し、そして我々はそれが上の注文のチーフ道をドライブしましょうコイン。
  • これはではありません。は、コインが本当にそのことを知る必要がないので、あらゆる種類の変換を記述していません。彼らは実際にそれらを変換する時まで、コインの間に価値がありません。 foreign exchange.
public class Copper extends Coin { 

    public Copper(final int volume, final int density, final int weight) { 
     super(volume, density, weight); 
    } 

    @Override 
    public int compareTo(final Coin otherCoin) { 
     if(otherCoin instanceof Copper) { 
      return (volume - getVolume()) + (density - getDensity()) + (weight - getWeight()); 
     } 
     // assume Coppers are worth the least 
     return Integer.MIN_VALUE; 
    } 
} 

他の通貨は、読者の練習として残していると思います。

私がカバーしたい最後のことは、すべての通貨に対して何らかの形のジェネレーターです。これは、反射魔法のビットが本当にあなたが気にしているコンストラクタを呼び出すのに役立つことができるところです。

私も、これは世代が何らかの理由で障害が発生した場合には、Optional<T extends Coin>ようを返す作った、あなたが代わりにnull動作するオプションを持っています。

public static void main(String[] args) { 

    final Optional<Copper> x = CoinFactory.generateCoin(10, 20, 30, Copper.class); 
    if(x.isPresent()) { 
     System.out.println(x.get()); 
    } 
} 
+1

抽象クラスに反対するコインを作ることについて、あなたはどのような考えを持っていますか?無関係な注記では、すべてのコインが良いものから変換することができるようにするために必要な「単位」メトリックを作成するでしょうか?どうやって 'TimeUnit'のようなコインタイプの列挙を維持し、各タイプのカウントを保持するのですか? in:財布クラス 'EnumMap <コイン、整数>コイン; – Aarjav

+0

どのような素晴らしい答えですか?私はこれを実現するための努力を感謝します。私はまず、Enumsを読み込み、それらを実装に統合しようと考えます。私は何かを明確にしたいと思います - 私は実際には、PurseオブジェクトのコインのArrayListが意味をなさないと思います。私は通貨を含む相互作用が外部クラスによって処理されることを望み、コインは単純な算術演算によって追跡されるべきであると思う。静的な値(またはenum?)は、操作のセマンティクスを決定するのに役立ちます。 –

関連する問題