我对类和继承的概念不熟悉,并认为我可能有点困惑。我正在尝试使用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
?
答案 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,它应该可以工作。