aspose file tools*
The moose likes Beginning Java and the fly likes ClassCastException Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login
JavaRanch » Java Forums » Java » Beginning Java
Bookmark "ClassCastException" Watch "ClassCastException" New topic
Author

ClassCastException

Carl Pettersson
Ranch Hand

Joined: Sep 09, 2003
Posts: 73
I have a class JavaStudent which extends the class Person, and I save instances of it in an ArrayList, which works fine. Problem is, it is for some reason saved as a Person instead of a JavaStudent. Why is that? I create the JavaStudent like this

Does that mean that I acually create a Person instead? Because when I try to access the methods which are "new" in JavaStudent, I get a ClassCastException
Phil Lesh
Greenhorn

Joined: Oct 16, 2002
Posts: 17
Hi,
When you are calling super(Fn, Ln, DoB), essentially what you are doing is saying Person(Fn, Ln, DoB) so it creates a Person object. What you should do is in your Person class, create/define common methods for Person which could be inherited by the JavaStudent class and any others you may wish to add (e.g. JavaTeacher class extending Person). I hope this helps!
Phil
Carl Pettersson
Ranch Hand

Joined: Sep 09, 2003
Posts: 73
When I call super(Fn, Ln, DoB), it just sets First and last namn and date of birth, but if I leave the call to super out, I get a "cannot resolve symbol constructor Person" error. Should I maybe change the way the constructor of Person works? It looks like this now
Jeremy Thornton
Ranch Hand

Joined: Feb 21, 2002
Posts: 91
I suspect that your constructor has nothing to do with your problem.
When you create an object using the constructor it constructs an object of the correct type, the call to super is used to construct the parts of the object that are derived from the super type.
I'm guessing that you are probably adding Person objects to the collection.
If you post a little of the code where you add and remove objects from the collection this would probably help.
William Barnes
Ranch Hand

Joined: Mar 16, 2001
Posts: 986

You need to cast what you get back from collections, to the proper sub-class. (Does that make any sense?)


Please ignore post, I have no idea what I am talking about.
Carl Pettersson
Ranch Hand

Joined: Sep 09, 2003
Posts: 73
This is the Create method which is inherited, and it adds a person. Should I redefine it?

When I get it, I cast it to a JavaStudent, which is where I get the ClassCastException I think
Ernest Friedman-Hill
author and iconoclast
Marshal

Joined: Jul 08, 2003
Posts: 24187
    
  34


Person MyPerson = new Person(Fn, Ln, Pn);

Right. Well, this explicitly creates a Person object, so that's what you'll get. Subclassing Person won't change the behavior of this method.
If you want to be able to have different subclasses create different kinds of objects, here's one way to do it: change that one line in Create() to look like

then define a method like this in the Person class:

Create() will now call this to make a Person. Now, here's the fun part. In subclasses of person, override makePerson to return an instance of the subclass instead:

When called on a subclass object, Create will now create an instance of the subclass.


[Jess in Action][AskingGoodQuestions]
Carl Pettersson
Ranch Hand

Joined: Sep 09, 2003
Posts: 73
Ah, smart! Thank you!
Carl Pettersson
Ranch Hand

Joined: Sep 09, 2003
Posts: 73
Hmm... It still doesn't work. If I check what class it is (via .getClass()), I still get class Person. My compiler told me that the new method couldn't be accessed from a static context, so I made it a static method just to try it out, does that make a difference?
[ October 30, 2003: Message edited by: Carl Pettersson ]
Ernest Friedman-Hill
author and iconoclast
Marshal

Joined: Jul 08, 2003
Posts: 24187
    
  34

Yes, it does. Static methods can't be overridden (you can define a new method in a subclass, but it won't act polymorphically -- i.e., a static Create() will only call the makePerson() defined in Person.) If you make all these methods static, then they won't work as advertised.
Carl Pettersson
Ranch Hand

Joined: Sep 09, 2003
Posts: 73
But why is the create method static then? It isn't defined as a static method...
/edit
Just to clarify: it was the makePerson method which was made static, not Create.
[ October 30, 2003: Message edited by: Carl Pettersson ]
Ernest Friedman-Hill
author and iconoclast
Marshal

Joined: Jul 08, 2003
Posts: 24187
    
  34

I thought you just said you made it into a static method?
"Can't be accessed in a static context" means that you're trying to call a non-static method from a static one (probably main().) You're trying to call Person.create() as if it were static. If it's non-static you have to call it "on" an object.
Carl Pettersson
Ranch Hand

Joined: Sep 09, 2003
Posts: 73
The program works like this;
The main method really doesn't do much, it initializes another non-static method.
This one runs a while-loop which just prints a menu and then has a switch-statement to check what the user wants to do.
Then it runs the right method, these methods are defined within the class PersonUtils. This class also is the one which contains the ArrayList where I keep the Persons/JavaStudents.
I made PersonUtils a class because I needed these methods to be extendable, they will be used and extended over the course of this year's Java-course.
[ October 30, 2003: Message edited by: Carl Pettersson ]
Jeremy Thornton
Ranch Hand

Joined: Feb 21, 2002
Posts: 91
Sounds like you are calling Person.create() somewhere (i.e. a static call) when you should be calling
// Person.create() - nope!
Person aPerson = new Student(...);
aPerson.create();
If you are going to use the template method mentioned earlier (calling an abstract method that has been defined in a subclass from within another method) then the methods need to be non-static to allow them to be overriden.
If I were you, I'd simplify the methods a little (just print out some text) so that you can see that the subclasses method is being used properly.
Without wishing to make things more complicated for you, I would consider moving the logic that adds Person objects into a collection outside the Person class hierarchy.
Jeremy.
Carl Pettersson
Ranch Hand

Joined: Sep 09, 2003
Posts: 73
The code for creating/adding the Person or Student object is outside the Person class entirly. I think I've understood why I am making a static call though, but not how I should solve it. After trying to use Ernest's way of creating a new Person, the Create method looks like this

If I do it this way, it says that MyPerson might not have been initiated, but if I change it to be Person.makePerson(Fn, Ln, Pn), then it is a static call, right? I don't really know how to solve this...
Jeremy Thornton
Ranch Hand

Joined: Feb 21, 2002
Posts: 91
What your trying to do seems a little odd.
The makePersion method seems like it should be a straightforward constructor. Rather than

You should be doing something like
Person myPerson = new Student(...);
The reason that your getting warnings is that you've created a person variable pointing to nothing (Person MyPerson ; ) and then tried to call a method on it.
Does this make sense?
Alternatively, if you are sure that you want to treat Person as a factory for creating subclasses you could do something like:

[ October 31, 2003: Message edited by: Jeremy Thornton ]
Carl Pettersson
Ranch Hand

Joined: Sep 09, 2003
Posts: 73
That works, but then I always create Persons, which means I will have to re-define Create() every time I want to create a new sort of PersonSubclass... Isn't there some nice way to do this? I've been beating my head against this problem for almost a week now, so probably the answer is right under my nose
Ernest Friedman-Hill
author and iconoclast
Marshal

Joined: Jul 08, 2003
Posts: 24187
    
  34

I could definitely tell you more, because what you're describing is a well-understood paradigm, but let's step back a little bit and try to get to the root of your problem first.
You've got a method in class Person which creates a bunch of instances of class Person.
You want to be able to subclass it and arrange things so that when you call this method from a subclass JavaStudent, it creates instance of JavaStudent instead.
Is that it?
If Create() is a static method, then it simply doesn't know which Class it was "called on", so just subclassing is not enough. There's no way to do this without telling the method what kind of object to create, by passing it a parameter, or by some other means. Simple as that.
If Create() is nonstatic, then it does know what class it's being called on, but then of course, you need an object of the right class to call it on, which is a problem.
So what we're talking about is called the "Factory Method design pattern." You can find material about it all over the Web. Have a look at the linked web page, find a few others for yourself, then come back and ask questions if you need it.
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: ClassCastException