Java中的类和继承 - 我做错了什么?

时间:2012-02-17 21:47:33

标签: java model-view-controller oop class

我对类和继承的概念不熟悉,并认为我可能有点困惑。我正在尝试使用MVC设计模式,所以如果我创建一个“基础”模型类,那么我可以从这一个继承我的所有其他模型,以便视图类可以接受对任何类型的模型的引用。这是我的尝试:

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);
...

这是我的扩展模型类之一:

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
    }
}

但是在尝试访问Maze内的额外SceneView字段时出现编译错误

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

9 个答案:

答案 0 :(得分:2)

我认为你想要的是这样的(取决于你是否定义Model)。这假设i不是每个Model都有的东西,否则将i移到模型的建议要简单得多(并将其保护为私有并使用getter)。

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

...

答案 1 :(得分:1)

由于SceneView构造函数已被声明为接受Model的参数,因此无论对象传递给哪个特定子类,它都只能看到Model中的成员和方法SceneView()是,因此无法看到i数据成员。

现在,为什么SceneView()需要看{4}}?如果i确实适用于SceneView的任何子类,则它不能依赖于子类中的任何内容。因此需要编写Model来执行Maze所需的任务 - 需要使用Maze完成特定的操作。

答案 2 :(得分:1)

传递泛型类型时,继承仅适用于传递的最通用类型的基本功能。因此,例如,在这种情况下,如果不是“每个”模型都有public int i;,那么你不能在没有类型转换的情况下直接访问它(我们将在稍后讨论)。此外,在这种特殊情况下,您只能访问模型类中显式定义的函数和变量,因为它们对于所有派生类都保证相同。

但是,现在,如果您确定您拥有给定类型的特定子类,那么您可以键入它并以这种方式访问​​成员。如果你不能保证这一点,这很危险,可能会导致一些不好的错误。

在这种情况下,要执行您想要的操作,请尝试System.out.println(((Maze)ms).i);

答案 3 :(得分:0)

您已在“迷宫”中定义了i,但尝试通过引用“模型”来访问它。

您可以将ms转换为Maze(并破坏所有类型的OOP规则),或者您必须将其作为Model的成员。

答案 4 :(得分:0)

它可能是Maze,但它也可能是Model的其他子类。这就是为什么你不能假装它绝对是Maze并访问它的成员,因为它可能不是一个。

如果您知道它是Maze,那么为什么不声明SceneView构造函数来获取Maze?如果你不能,你仍然可以施放它:((Maze) ms).i但这是一个很臭的代码。

答案 5 :(得分:0)

不,问题是您传递了Model,但Maze是具有公共变量i的类。 (顺便说一句,不好的主意。你的理解存在很大的问题。)

我想你想把i拉到Model级。一切都会很好。

如果您传入Maze,一切都会很好,因为Liskov替换原则是Maze IS-A Model,因此您可以将其传递给SceneView没有问题。

答案 6 :(得分:0)

即使它实际上是Maze,您也将其声明为Model。编译器将检查Model的属性,因此您将收到编译器错误。你可以施展它,它会起作用。

答案 7 :(得分:0)

你总是可以通过

重新制作它
if(ms instanceof maze.class){
//recast back to maze
}

但它有点像hacky,并且总是不赞成。

答案 8 :(得分:0)

如果将参数i从类Maze移动到类Model,它应该可以工作。