在Java中充分利用多态性
我有以下问题: 假设我们有3个类:在Java中充分利用多态性,java,polymorphism,abstract-class,Java,Polymorphism,Abstract Class,我有以下问题: 假设我们有3个类: 一个名为Vehicle 一个名为摩托车的类别扩展了车辆 一个名为Car的类,扩展了Vehicle 这意味着车辆对象可以同时容纳摩托车和汽车对象 我还有一个名为VehicleDatabase的类,它基本上“模拟”了一个数据库(我希望我可以使用数据库,但这是一个大学项目),并持有一个名为db的ArrayList字段,以及一些提供一些基本操作的方法,以便我可以与数据库交互(积垢操作和其他一些) 我想要实现的一种方法是showVehicles()。为了简化并达到我
- 一个名为
Vehicle
- 一个名为
的类别扩展了摩托车
车辆
- 一个名为
的类,扩展了Car
Vehicle
车辆
对象可以同时容纳摩托车
和汽车
对象
我还有一个名为VehicleDatabase
的类,它基本上“模拟”了一个数据库(我希望我可以使用数据库,但这是一个大学项目),并持有一个名为db
的ArrayList
字段,以及一些提供一些基本操作的方法,以便我可以与数据库交互(积垢操作和其他一些)
我想要实现的一种方法是showVehicles()
。为了简化并达到我问题的要点,假设此方法必须简单地将函数参数指定的所有对象的.toString()
打印到控制台
示例:
用户界面中将显示一个菜单:
Select which type of vehicles you want to be shown:
1.Motorcycles
2.Cars
Make your choice:
在此之后,我们的函数showVehicles
必须采用一个参数,例如showVehicles(CarSomething)
并打印存储在db
ArrayList上的所有汽车。我真的找不到更优雅的方法来实现该函数。以下是我当前的实现:
public void showVehicles(Class<?> cls)
{
for(Vehicle v : db)
{
if(v.getClass().equals(cls))
System.out.println(v.toString());
}
}
公共车辆(cls类)
{
用于(车辆v:db)
{
如果(v.getClass().equals(cls))
System.out.println(v.toString());
}
}
然后像这样调用它:showVehicles(Car.class)
或showVehicles(Motorcycle.class)
有没有更好的方法可以做到这一点?请给出您的建议。我只是觉得我没有像应该的那样使用多态性。实际上,这不是面向对象方法通常使用的方式。下面是一个多态方法的示例。“printName”函数是在抽象类中定义的(在这种情况下也可以是接口):
import java.util.ArrayList;
抽象类车辆{
公共抽象void printName();//虚拟函数
}
二等车{
public void printName(){//类Car中的函数实现
System.out.println(“我是一辆车”);
}
}
二等车{
public void printName(){//类中的函数实现
System.out.println(“我是一辆自行车”);
}
}
公共类T1{
ArrayList车辆=新ArrayList();
void create(){
车辆。添加(新车());
车辆。添加(新自行车());
}
作废清单(){
用于(车辆v:车辆)
v、 printName();//在显示时使用该函数
}
公共静态void main(字符串参数[]){
T1=新的T1();
t1.create();
t1.list();
}
}
如果您想使用真实的数据库,则会有很大的不同。后者只能保存java类中的
数据字段并将其还原到类中。因此,您的应用程序必须在读取时了解这些类,并确保正确的类中填充了正确的数据。在这种情况下,序列化会有所帮助。这里是一种可能性
我创建了一个Map,List>inventory=List.stream().collect(
Collectors.groupingBy(Object::getClass));
}
}
这是否是一个合理的方法取决于您(以及其他评论者)。您可能仍然需要一个映射来从用户菜单获得正确的类
Map<String, Class<?>> menuMap = new HashMap<>();
menuMap.put("Car", Car.class);
menuMap.put("MotorCycle", MotorCycle.class);
Class<?> lookup = menuMap.get("Car");
for (Vehicle v : inventory.get(lookup)) {
System.out.println(v.toString());
}
Map lookup=menuMap.get(“汽车”);
对于(车辆v:库存获取(查找)){
System.out.println(v.toString());
}
好吧……现在你知道为什么没有“对象关系映射器”了。关系数据库存储数据,而对象是关于行为的。在你的小例子中,你仍然能够确定一些车辆
是汽车
还是摩托车
。这是不正确的(如果不存储其他信息,则至少不存储)如果你使用一个真实的数据库。为了避免这个问题,你是否考虑将它们存储在<代码> map < /COD>其中字符串是实际的车辆类型?@ WJS需要使用<代码> MAP>代码>来存储每个类的多个实例或<代码> MAP>代码>,将类名存储为值,而不是键。ode>Class
-实例,而不是类的名称为String
@Turing85。我同意。我不会说这会使我的方法更方便,但它确实是实现我尝试的方法的更好方法。到目前为止,最好的答案是,如果没有更好的方法出现,我会接受它。我本来打算做Map(我忘了列表部分)但是@Turing85让我保持诚实,还建议使用类实例作为键。我看到了评论,也为@Turing85感到荣幸。老实说,我不认为有更好的方法可以做,这通常是关系数据库的工作,而不是Java的。但我认为这会打印ArrayList的每个元素……这不是这不是我所期望的明确的行为。
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
abstract class Vehicle {
}
class MotorCycle extends Vehicle {
String name;
MotorCycle(String name) {
this.name = name;
}
public String toString() {
return name;
}
}
class Car extends Vehicle {
String name;
Car(String name) {
this.name = name;
}
public String toString() {
return name;
}
}
public class CarMapper {
public static void main(String[] args) {
List<Vehicle> list = new ArrayList<>();
list.add(new MotorCycle("Honda"));
list.add(new MotorCycle("Harley-Davidson"));
list.add(new Car("Ford"));
list.add(new Car("Chrysler"));
Map<Class<?>, List<Vehicle>> inventory = list.stream().collect(
Collectors.groupingBy(Object::getClass));
}
}
Map<String, Class<?>> menuMap = new HashMap<>();
menuMap.put("Car", Car.class);
menuMap.put("MotorCycle", MotorCycle.class);
Class<?> lookup = menuMap.get("Car");
for (Vehicle v : inventory.get(lookup)) {
System.out.println(v.toString());
}