我是Java编程的新手,试图掌握OOP的诀窍。
所以我创建了这个抽象类:
public abstract class Vehicle{....}
和2个子类:
public class Car extends Vehicle{....}
public class Boat extends Vehicle{....}
Car和Boat还拥有一些不常见的独特字段和方法(没有相同的名称,所以我无法在Vehicle中为它们定义抽象方法)。
现在在mainClass中我已经设置了我的新车库:
Vehicle[] myGarage= new Vehicle[10];
myGarage[0]=new Car(2,true);
myGarage[1]=new Boat(4,600);
我对多态性非常满意,直到我尝试访问Car特有的一个字段,例如:
boolean carIsAutomatic = myGarage[0].auto;
编译器不接受。我使用类型转换解决了这个问题:
boolean carIsAutomatic = ((Car)myGarage[0]).auto;
工作……但它对方法没有帮助,只对字段有帮助。意思是我做不到
(Car)myGarage[0].doSomeCarStuff();
我的问题是,我的车库里到底有什么?我试图获得直觉,并理解“幕后”发生了什么。
为了方便以后的读者,以下是对答案的简要总结:
Yes, there's a Car in myGarage[]
Being a static typed language, the Java compiler will not lend access to methods/fields that are non-"Vehicle", if accessing those through a data structure based on the Vehicle super class( such as Vehicle myGarage[])
As for how to solve, there are 2 main approaches below:
Use type casting, which will ease the compiler's concerns and leave any errors in the design to run time
The fact that I need casting says the design is flawed. If I need access to non-Vehicle capabilities then I shouldn't be storing the Cars and Boats in a Vehicle based data structure. Either make all those capabilities belong to Vehicle, or use more specific (derived) type based structures
In many cases, composition and/or interfaces would be a better alternative to inheritance. Probably the subject of my next question...
Plus many other good insights down there, if one does have the time to browse through the answers.
Modeling objects you want to present in a program (in order to solve some problem) is one thing, coding is another story. In your code, I think essentially it's inappropriate to model a garage using array. Arrays shouldn't be often considered as objects, although they do appear to be, usually for the sake of self-contained-ness sort of integrity of a language and providing some familiarity, but array as a type is really just a computer-specific thing, IMHO, especially in Java, where you can't extend arrays.
我知道正确地建模一个类来表示车库并不能帮助回答“车库中的汽车”的问题;只是一个建议。
回到代码。除了一些面向对象的问题之外,一些问题将有助于创建一个场景,从而更好地理解你想要解决的问题(假设有一个问题,而不仅仅是“得到一些问题”):
谁或什么东西想了解carIsAutomatic?
给定carIsAutomatic,谁或什么将执行doSomeCarStuff?
It might be some inspector, or someone who knows only how to drive auto-transmission cars, etc., but from the garage's perspective, all it knows is it holds some vehicle, therefore (in this model) it is the responsibility of this inspector or driver to tell if it's a car or a boat; at this moment, you may want to start creating another bunch of classes to represent similar types of *actor*s in the scene. Depends on the problem to be resolved, if you really have to, you can model the garage to be a super intelligent system so it behaves like a vending machine, instead of a regular garage, that has a button says "Car" and another says "Boat", so that people can push the button to get a car or a boat as they want, which in turn makes this super intelligent garage responsible for telling what (a car or a boat) should be presented to its users; to follow this improvisation, the garage may require some bookkeeping when it accepts a vehicle, someone may have to provide the information, etc., all these responsibilities go beyond a simple Main class.
说了这么多,当然我理解编写面向对象程序的所有麻烦,以及样板,特别是当它试图解决的问题非常简单时,但面向对象确实是解决许多其他问题的可行方法。根据我的经验,有了一些提供用例的输入,人们开始设计对象如何相互交互的场景,将它们分类为类(以及Java中的接口),然后使用像Main类这样的东西来引导世界。