2012-02-17 14 views
1

私はクラスと継承という概念を初めて使い、少し混乱しているかもしれないと思います。私はMVCデザインパターンを使用しようとしているので、 "ベース"モデルクラスを作成すると、ビュークラスがあらゆる種類のモデルへの参照を受け入れることができるように、このモデルから他のすべてのモデルを継承できます。ここJavaのクラスと継承 - どうしたのですか?

public class SceneControl { 
    SceneView scMaze; 
    SceneView scOptions; 
    Model ms; 

    public SceneControl(ViewPanel view) { 
     this.view = view; 

     ms = new Maze(31, 20, 5); 
     SceneView scMaze = new SceneView(ms); 
     ms = new Options(20, 20, 20, 200, 20); 
     SceneView scOptions = new SceneView(ms); 
... 

と私の拡張モデルクラスの1つです:ここに私の試みです

public class Maze extends Model { 
    public int i; 

    public Maze(int cols, int rows, int ratio) { 
     super(cols, rows, ratio); 
     i=77; // a test- can I access this field from inside SceneView 
    } 
} 

しかしSceneView内の余分なMazeフィールドにアクセスしようとしたとき、私はコンパイルエラーに取得

public Model ms; 

public SceneView(Model ms) { 
    this.ms = ms; 
    System.out.println(ms.i); //gives "connot be resolved or is not a field" error 
... 

私はオブジェクトがMazeからModelにダウンキャストされていると推測していますか?どのようにそれを私のビュークラスにModelのように渡すことができますが、それでもまだ実際にはMazeでしょうか?

+0

あなたは 'Model'、ない' Maze'を持っています。 'Model'には' i'という名前の公開ファイルが含まれていません –

+0

答えよりもRahter、私はMaze以外の別のModelサブクラスを渡そうとするとどうなると思いますか?フィールドiを定義しなかったか? –

+0

こんにちは@ケビン、私は別のサブクラスを区別するために後でif()ステートメントを使用する予定だった...これは悪いOOPですか? –

答えて

2

あなたが望むと思うものは、これが(Modelを定義するかどうかによって異なります)。これは、iがすべてModelにあるものではないことを前提としています。そうでなければ、モデルをiモデルに移動するという提案はずっと簡単です(プライベートとして保護し、ゲッターを使用します)。

public abstract class Model { // or even interface 
    public String modelAsString(); // possibly just use Object.toString() 
} 

public class Maze extends Model { // or implement, if Model is interface 
    private int i; 
    ... 
    public String modelAsString() { return "i = " + i; } 
} 

public SceneView(Model ms) { 
    this.ms = ms; 
    System.out.println(m.modelAsString()); // Now any Model subtype will work 

...

+0

喜んで@ケビン、そのように文字列にエンコードされているなどの基本クラスからアクセス可能な共通の形式に各モデルをエンコードするメソッドを使用することをお勧めですか? –

+1

はい、この場合、Stringは非常に単純化されていますが、ビューのニーズに応じてさらに複雑なものが必要になることがあります。 –

0

あなたは "迷路"でiを定義しましたが、 "モデル"への参照を通してそれをアクセスしようとしました。

msをMazeにキャストしたり、あらゆる種類のOOPルールを破ることができます。または、それをModelのメンバーとして配置する必要があります。 SceneViewコンストラクタはModelの引数を取るように宣言されたので、それはiを見ることができないので、

+0

こんにちは@akhisp、私は申し訳ありませんが、私はまだJavaの用語で100%ではない。 「Maze」をモデルの内部クラスとして、あるいは独立クラスとして「モデル」からインスタンス化することを意味しますか? –

+0

彼は変数 'i 'を迷路からモデルに移動することを意味します。クラスの「メンバー」である変数は、しばしば「フィールド」と呼ばれます。または "インスタンス変数"。 –

1

、それだけで、関係なく、SceneView()に渡されたオブジェクトが何であるかを特定サブクラスのModelであるメンバーとメソッドを見ることができますデータメンバー。

SceneView()はなぜiを参照する必要がありますか? SceneViewが実際にModelのサブクラスで動作しようとしている場合、サブクラスの何かに依存することはできません。したがってMazeは、iで行われる必要があるすべてのMaze固有の処理を行うように記述する必要があります。

+0

こんにちは@QuantumMechanic、ありがとう。したがって、良いOOP設計では、どのサブクラスにも固有のものは、キャスティングを使用するのではなく、クラス自体によって処理されると言いますか?しかし、確かにこれは私のMVCデザインパターンを壊すだろうと私は 'Maze'クラスは、それがモデルのものだけを行うことになっているときに画面にレンダリングする必要がありますか? –

+0

Mazeはレンダリング自体を行う必要はありません。適切な入力だけを提供する必要があります。しかし、MVCの適切な責任について考えていることは良いことです。そのことにうんざりするのは簡単です。 –

1

汎用型を渡す場合、継承は渡された最も一般的な型の基本機能でのみ機能します。たとえば、この場合、「すべての」モデルにpublic int i;が含まれていると、タイプキャストなしで直接アクセスすることはできません(これはすぐに取得されます)。さらに、この特定のケースでは、モデルクラスで明示的に定義された関数と変数にのみアクセスできます。これは、すべての派生クラスで同じことが保証されているためです。

ただし、特定のタイプの特定のサブクラスがあることがわかっている場合は、それを型キャストしてメンバーにアクセスできます。あなたがこれを保証することができない場合、これは危険であり、いくつかの悪いバグを引き起こす可能性があります。この場合

は、あなたがしたいものを行うために、それはMazeかもしれませんが、それはまたModelのいくつかの他のサブクラスである可能性がありSystem.out.println(((Maze)ms).i);

0

を試してみてください。だからこそ、それは間違いなくMazeであるとふりかけることはできません。

どういうわけか知っていれば、Mazeだと、SceneViewコンストラクタをMazeとすることをなぜ宣言しないのですか?もしあなたができないのであれば、それでもキャストすることができます:((Maze) ms).iしかし、これは臭いコードです。

0

いいえ、問題はModelですが、Mazeは公開変数iを持つクラスです。 (あなたの理解に大きな問題があります)

i私はModelクラスまで引き上げたいと思います。すべてがうまくいくでしょう。あなたはMazeに渡す場合

、リスコフの置換原則はMazeは、IS-Model言うので、すべてがうまくなりますので、あなたは問題なくSceneViewにそれを渡すことができます。

+0

アンナへの私のコメントを参照してください。 'i'を' Model'に引っ張ることは '' Model''のすべてのサブクラスで '' i''が意味がある場合にのみ意味があります。 'i'が何らかの' Maze'特有のものであれば、それを基底クラスに引っ張ってはいけません。 – QuantumMechanic

+0

それから迷路はモデルではありません。またはその方法は迷路を取る必要があります。あなたのデザインはまだ間違っています。 – duffymo

0

実際にはMazeですが、あなたはModelと宣言しました。コンパイラはModelの属性をチェックするため、コンパイラエラーが発生します。あなたはそれを投げることができ、それはうまくいくでしょう。

+0

あなたはそれをキャストできますが、それは一般的に欠陥のあるデザインの兆候です。 – QuantumMechanic

+0

@QuantumMechanicは、なぜこれが欠陥のあるデザインの兆候であるかのようにキャストする必要があるかについて、より多くの光を放つことができますか?私はOOPを全く新しくしていますが、私のビュークラスはすべてのタイプのモデルクラスへの参照を受け入れることができるので、私にとって意味があります。それは良いOOPデザインでどのように行われますか? –

+0

まあ、それは依存しています。 'i'が' Model'のすべてのサブクラスで実際に使用されるものであれば、それを 'Model'に移すのは意味があります。しかし、もし私が '迷路'だけに意味をなさせるものであれば、そうしなければならない。なぜなら、もしあなたがしたら、ある特定のタイプの 'Model'に意味をなさないものをすべてのタイプモデルの。それは良いデザインではありません。 – QuantumMechanic

0

あなたは常に

if(ms instanceof maze.class){ 
//recast back to maze 
} 

ことによってそれをバックリキャストでしたが、それはちょっとハックであり、一般にひんしゅくを買います。

0

パラメータiをクラスMazeからクラスModelに移動すると機能します。

+0

しかし、 'i'が' Maze'に固有の状態を記述すると、 'Model'に入れるべき理由はありません。 – QuantumMechanic

関連する問題