Creating instances of inherited classes in Java

I have a class “Student” that extends an abstract class “Person”. If you were instantiating a new Student object, would you code:


Student newStudent = new Student( "John Doe" ); // Call this one 'A'

or


Person newStudent = new Student( "John Doe" ); // Call this one 'B'

Both forms appear to work the same, but my teacher and I keep arguing about which is preferable. I say A, she says B. I’ve looked it up in my two textbooks, and one uses A and one uses B.

So the questions are:

  1. What’s the difference? (if any)
  2. Which style is better? (if either)

And no, this is NOT a homework question.

Why does she think that the second one is preferable?

Because it’s what the textbook we’re using in class uses. (Java Outside In: a thouroughly terrible book, IMHO) I actually think it’s a horrible idea, and it wouldn’t even compile if I were designing the language. It’s especially confusing when I type:


Person aStudent = new Student( "John Doe" );
aStudent.showCurrentGPA(); // showCurrentGPA() defined in class Student

The actual meaning of the code seems very muddled to me, since a generic Person object shouldn’t have a showCurrentGPA() method.

Your teacher is a boob.

Which is preferable is completely context-dependent.

If you need to use the generic class (Person) for, say, passing to a method that specifies ‘Person’ as a parameter, then use method ‘b’.

On the other hand, if you’re planning on using the object as a Student, might as well refer to it as Student when you instantiate it.

Really, either way is fine. The only thing you’re risking is that might have to cast it later on, and the code will be easier to read without a bunch of casts.

If your teacher says that ‘a’ or ‘b’ is preferable in all situations, she’s wrong.

On second thought, yeah, what Friedo said.

I would have to double check this but I believe that method A will also work in this situation due to how Java implements polymorphism (dynamic binding).

The only time I would use A is if newStudent could somewhere else be assigned an object of class Person or some other subclass of Person, but the naming in your example makes this seem unlikely.

What level of school is this? What are the credentials of your teacher?

(Teachers are not always right. I had to correct my daughter’s fourth grade teacher when she said that “another name for the Prime Meridian is the International Dateline.”)

It sounds like your book/teacher is trying to present dynamic dispatch and failing miserably. Shame, really, as that’s one of the most important ideas in object-oriented programming.

If you need methods of the Student class, then obviously you have to use it. If you don’t need methods of the Student class(ie the only methods that you’ll be calling are declared in the Person class), then this really becomes a matter of style*. When it comes to matters of style, you can’t say that one is “better” than another (well, unless the “style” in question is something ludicrous like using no newlines whatsoever).

However, when it comes to matters of style, you should go with the style your boss mandates. In this case I agree that it’s silly, but is it really worth the effort to fight it?

  • Well, I suppose given a sufficiently clever JIT compiler you might see a slight performance enhancement from using A, but it’s also possible that the compiler could be smart enough to apply the same optimization using style B anyway.

Sometimes. I got my first job because I described an argument I had with a teaching assistant in college when I thought I was right about a structured design issue. The hiring manager agreed with me and liked that I would stand up for an idea I thought was right.

I was talking about style issues, not design issues. Style is mostly a matter of personal preference.

Actually it is very important for an OO language that it should compile.

and that should not.

Style ‘A’ would be appropriate where we are interested in the Student-ness of newStudent. Style ‘B’ when we are only interested in newStudent’s Person-ness.

That won’t compile.

Agreed with Athena.

It will if showCurrentGPA() is defined in the Person class.

:smack:
Declared. I meant declared.

One reason you might want to assign the new Student to a Person variable is to take advantage of polymorphism. Consider the following:

Person
personFactory(String name, int salary) {
Person newPerson;

if (salary == 0) {
    newPerson = new Student(name);
} else {
    newPerson = new Teacher(name, salary);
}

 return newPerson;

}

Your teacher might have something like this in mind - that is, in the context where you’re creating the object, there might be a good reason to use a superclass variable.

Polymorphism is the whole reason you would want to refer to objects of derived classes by their common base class - hoard together a bunch of objects irrespective of their specialized types, and take advantage of dynamic binding to allow each to exhibit its specialized behavior.

If all you’re going to do is have one Student object, and use it as a Student object, it would make more sense to give the reference to the object the Student type, so you can access Student’s methods without casting. The whole advantage of the Person->Student heirarchy is generality - a Student “is a” Person, an Engineer “is a” Person, so the behavior common to Persons can be kept in the common superclass. The thing to remember is that in your initial declaration (“Student newStudent = new Student(…);”), that first typename is only the type of the reference - a label, a handle to the actual object. It can be as specific to your type as you need it to be.

Polymorphism is very useful for OOP, so you should learn to love it. :slight_smile:
Oh, and Rysto, I think the OP mentioned that showCurrentGPA was declared in the Student class.