简体   繁体   English

继承与多态Java

[英]inheritance and polymorphism java

I have an array of objects of my base class, Customer. 我有一个基类客户的对象数组。 It has 3 sub-classes Account1, Account2 and acount3. 它具有3个子类Account1,Account2和acount3。 When i run through a loop checking every account for its type and then assigning it appropriately, in the end i just get empty data fields. 当我循环运行时,检查每个帐户的类型,然后适当地分配它,最后,我只会得到空的数据字段。

Is something like this possible to do? 这样可以做吗?

                 public static int readFile(String filename, Customer[] review)throws IOException{

                 Scanner scan = new Scanner (new File (filename));

                /*Reading the first record separatly*/
                  Customer first = new Customer();
                  Account1 first1= new Account1();
                  Account2 first2= new Account2();
                  Account3 first3 = new Account3();

                  String[] a = scan.nextLine().split("=");
                  first.set_account_id(Integer.parseInt(a[1].trim()));

                  a = scan.nextLine().split("=");
                  first.set_name(a[1].toUpperCase().trim());

                  a = scan.nextLine().split("=");
                  first.set_address(a[1].trim());
                  a= scan.nextLine().split("=");                                                                  
          first.set_accType(a[1].trim());

                  if (first.get_accType().equals("Saving")){
                      first = first1;
                  }

                  else if(first.get_accType().equals("Checking")){

                      first = first2;
                  }

                 else if(first.get_accType().equals("Fixed")){

                      first = first3;
                      a = scan.nextLine().split("=");
                      first3.set_intRate(Double.parseDouble(a[1].trim()));
                  }

This code gives me empty data fields for my objects.. 此代码为我的对象提供了空的数据字段。

First of we have to make a distinction between an object and a variable. 首先,我们必须区分对象和变量。 A variable of type Customer can hold a reference to any object of the the type Customer or any object that is of type derived from Customer. 客户类型的变量可以保存对客户类型的任何对象或从客户派生的类型的任何对象的引用。 Assignment sets the variable to reference a different object. 分配将变量设置为引用其他对象。 Assignment does not alter the object itself at all. 分配根本不会改变对象本身。 By this reasoning, the assignment won't result in loss of data. 通过这种推理,分配不会导致数据丢失。

Now, you asked if an object of the base class can be assigned to a variable used to hold the derived type eg SubClass obj = new BaseClass() . 现在,您询问是否可以将基类的对象分配给用于保存派生类型的变量,例如SubClass obj = new BaseClass() This cannot be done as an object of the base class is not an object of a derived type. 这不能完成,因为基类的对象不是派生类型的对象。 The other way around it is possible eg 'BaseClass obj = new SubClass()' as an object of a derived type is a object of the base class. 另一种可能的解决方法是,例如'BaseClass obj = new SubClass()',因为派生类型的对象是基类的对象。

However, if you have a variable that holds a reference to the base type and an object of a derived type is assigned to this variable, you can assign the object the object to variable of the derived type using casting: 但是,如果您拥有一个对基本类型的引用的变量,并且派生类型的对象已分配给此变量,则可以使用强制转换将该对象的对象分配给派生类型的变量:

BaseClass obj = new SubClass();
Subclass subObj = (SubClass) obj; 

In you example you do the following: 在您的示例中,您将执行以下操作:

  1. You create a Customer object and assign a reference to the variable first 您创建一个Customer对象,并首先分配对该变量的引用
  2. You alter the state of the Customer object that is referenced in the variable first 您首先更改变量中引用的Customer对象的状态
  3. You replace the reference in the variable first with a reference to an Account1 object 您首先用对Account1对象的引用替换变量中的引用

This chain of events will not lead to the intended result, which I gather is that the setName and setAdd methods are called in the Account1 object. 这一系列事件不会导致预期的结果,我收集到的是在Account1对象中调用了setName和setAdd方法。 In effect the assignment first = first1 will reset the situation when seen through the variable first (the internal state of the object first and first1 remains unaltered). 实际上,当通过变量first观察时,赋值first = first1将重置情况(对象first和first1的内部状态保持不变)。

What you intend to do should be done as follows 您打算做的事情应该按照以下步骤进行

  private static String nextProperty(Scanner scanner) {
      return scanner.nextLine().split("=").trim()
   }


   public static int readFile(...) {
      ... 
   final int accountId = Integer.parseInt(nextProperty(scan));
   final String accountName = nextProperty(scan);
   final String accountAddress = nextProperty(scan); 
   final String accountType = nextProperty(scan); 

   Customer account = null;
   if(accountType.equals("Saving")) {
      account = new Account1();
   } else if (accountType.equals("Checking")) {
      account =  new Account2();
   } else if (accountType.equals("fixed")) {
      account = new Account3();
      ((Account3)account).set_intRate(Double.parseDouble(nextProperty(scan)));
   } else {
      throw new IllegalStateException("Unexpected account type encountered");
   }
   account.set_account_id(accountId);
   account.set_name(accountName);
   account.set_address(accountAddress);
   account.set_accType(accountType);
   ...

  }

You can always assign an object of a subclass to a variable of a superclass type, but not the other way round. 您始终可以将子类的对象分配给超类类型的变量,但反之则不能。

Regarding your edited version: what you do is syntactically correct (ie compiler wont complain), however it does not do what you want to do: from your input you set specific properties of first, ( first.set_address(a[1].trim()) ) but all those changes will 'get lost' when you overwrite the reference to first in 关于您的编辑版本:您的操作在语法上是正确的(即编译器不会抱怨),但是它并没有执行您想要的操作:从输入中设置first的特定属性,( first.set_address(a[1].trim()) ),但是当您覆盖first in的引用时,所有这些更改都将“丢失”

              if (first.get_accType().equals("Saving")){
                  first = first1;

The short answer is no: You cannot assign an object of some base class to one of a derived class at all . 简短的回答是否定的:你不能在所有的一些基础类的一个对象分配给一个派生类中的一个。 More broadly, you cannot assign any object to another object. 更广泛地说,您不能将任何对象分配给另一个对象。 Unlike C++, there is no such operation defined in Java. 与C ++不同,Java中没有定义此类操作。

If you're thinking of the = assignment operator, what you're assigning there are not instances of classes you've defined; 如果您想到的是=赋值运算符,则您要分配的内容中没有您定义的类的实例; you're assigning references to instances, or, if you prefer, pointers to instances. 您正在为实例分配引用 ,或者,如果您愿意,则为实例分配指针 These references are copied by value —like primitive integers—but nothing happens to the object instances to which those references point. 这些引用是按值复制的就像原始整数一样,但是这些引用指向的对象实例没有任何反应。

At present, there are no user-defined value types in Java; 目前,在Java中没有用户定义的值类型 any type defined by a user is always manipulated by reference, and there's no built-in way to assign—in the destructive, mutative sense of assignment in C++—one object instance to another. 用户定义的任何类型总是由引用来操纵,并且没有内置的方式(在C ++中以破坏性的,可变的分配方式)将一个对象实例分配给另一个。

The Java syntax makes it look as though something like that is going on, but it's important to remember that all assignment in Java happens by value , so long as the values in play are either primitives or references to object instances. Java语法使它看起来好像正在发生这种情况,但是请记住,Java中的所有赋值都是通过value发生 ,这很重要,只要游戏中的值是基元或对对象实例的引用即可。 The = assignment operator does not operate on object instances by value, but rather on references to those object instances by value. =赋值运算符不按值对对象实例进行操作,而是按值对这些对象实例引用进行操作

简单答案:不会丢失任何数据!

You should construct an object of the correct type, then refer to it as an instance of the superclass - ie Customer - this will then allow you to set some generic values. 您应该构造正确类型的对象,然后将其称为超类的实例(即Customer),这将允许您设置一些通用值。

Customer customer;
if (<insert test to tell if this should be of type Account1>){
     customer = newAccount1();
}
else if (<insert test to tell if this should be of type Account2>){
     customer = newAccount2();
}
else {// I'm assuming all others will be of type Account3, however if this is not the case you'll have to decide what to do
              customer = new Account3(); 
}
customer.setName("abc");
customer.setAdd("xyz new york");

Yes, it is possible. 对的,这是可能的。 In Java you can instantiate a sub class using it's base classe as a type (assigning as well). 在Java中,您可以使用其基类作为类型实例化子类(也可以进行赋值)。 You probably have used it without noticing, but every class in java extends the Object class so doing this (for example) would be right: 您可能没有注意到就使用了它,但是java中的每个类都扩展了Object类,因此(例如)这样做是正确的:

Object o = new Integer(12);

The example in itself is pretty useless, but for demonstration purpouses it works. 这个例子本身是没有用的,但出于演示目的,它是可行的。 This method was used way before generics existed in the Java definition. 在Java定义中没有泛型之前就使用了此方法。

Hope it helps! 希望能帮助到你!

In Java, the = operator does not assign objects, it assigns references. 在Java中, =运算符不分配对象,而是分配引用。 Assigning a reference does not modify the object it refers to. 分配引用不会修改其引用的对象。

An assignment is valid if the compile-time type of the left hand side is the same or a supertype of the type on the right hand side. 如果左侧的编译时类型与右侧的编译时类型相同或超类型,则分配有效。

If the left hand type is a subtype or the right hand type, the assignment is not valid. 如果左手类型是子类型或右手类型,则分配无效。 One way to get around this is by casting: 解决此问题的一种方法是通过强制转换:

Sub sub = (Sub) sup;

If at runtime sup isn't null and doesn't point to an object that is an instance of Sub , this will throw a ClassCastException . 如果在运行时sup不为null且未指向作为Sub实例的对象,则将抛出ClassCastException

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM