简体   繁体   中英

inheritance and polymorphism java

I have an array of objects of my base class, Customer. It has 3 sub-classes Account1, Account2 and 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() . 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.

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
  2. You alter the state of the Customer object that is referenced in the variable first
  3. You replace the reference in the variable first with a reference to an Account1 object

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

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

              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.

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

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. 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;
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). You probably have used it without noticing, but every class in java extends the Object class so doing this (for example) would be right:

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.

Hope it helps!

In Java, the = operator does not assign objects, it assigns references. 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 .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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