1

I'm trying (studying how to) to take advantage of creating abstract class and then subclasses etc. I have superclass Person:

public abstract class Person {
private String name;
private String type;

public String getType() {
    return type;
}
public void setType(String type) {
    this.type = type;
}
public String getName() {
    return name;
}
public void setName(String name) {
    this.name = name;
}
}

And subclasses, for example:

public class Man extends Person{
    private String occupation;
    public void setOccupation(String occupation) {
    this.occupation = occupation;
    }
    public String getOccupation() {
    return occupation;
    }
    @Override
    public void setType(String type) {
        super.setType(type); 
    }
    @Override
    public String getType() {
        return super.getType(); 
    }
    @Override
    public void setName(String name) {
        super.setName(name); 
    }
    @Override
    public String getName() {
    return super.getName(); 
    }

}

and a Teenager:

public class Teenager extends Person{
private String stdyPlace;
    public String getStdyPlace() {
    return stdyPlace;
}

public void setStdyPlace(String stdyPlace) {
    this.stdyPlace = stdyPlace;
}

@Override
public void setType(String type) {
    super.setType(type); 
}

@Override
public String getType() {
    return super.getType(); 
}

@Override
public void setName(String name) {
    super.setName(name); 
}

@Override
public String getName() {
    return super.getName();
}

So, further I want to do different acts depends on object type. I wanted smth like:

        Person pM;

    switch (typeOfPerson){
        case "Man": pM=new Man(); pM.setOccupation("military"); ...other acts  that regards this type of object...;  break; //doesn't work
        case "Student": pM=new Teenager(); pM.setStdyPlace("Boston"); ...other acts  that regards this type of object...; break;     //doesn't work too           
    }
    pM.setName(en);
    pM.setType(tp);

But the problem is, pM behave like a Person only. I can't find out how to cast it to type I want. Question is: how to cast it?

Sergey Lotvin
  • 179
  • 1
  • 14
  • Why are you overriding the `name` and `type` getters and setters, if all you do is call `super`? They are inherited, you know. – Andreas May 02 '16 at 21:20
  • Because I didn't know I shouldn't do it. Now I know - it's senseless. – Sergey Lotvin May 02 '16 at 21:29
  • I believe, that better (or at least more [OO](https://en.wikipedia.org/wiki/Object-oriented_programming)) way to do, what you want to do, is to use [polymorphism](https://docs.oracle.com/javase/tutorial/java/IandI/polymorphism.html) instead of using `switch` and `instanceof` ([find out why](https://www.google.pl/search?q=Polymorphism+vs+if+else&ie=utf-8&oe=utf-8&gws_rd=cr&ei=Nc4nV9CZCYPIsQGQ2pfgDA#q=polymorphism+vs+conditionals)). – TeWu May 02 '16 at 22:02

4 Answers4

2

Use the instanceof operator:

if (pM instanceof Man) {
    Man m = (Man) pM;
    //use 'Man' methods
}

This tells you whether or not a class instance is a type of a subclass. You should do this if you don't know the concrete class type and want to downcast.

Rogue
  • 11,105
  • 5
  • 45
  • 71
  • I didn't catch the idea. But I expect **pM** to be different. The type of **pM** depends on some other variable, for example **typeOfPerson**. I mean if it is **Man** I want to set occupation, if **Teenager** there other method etc. But for both there are **pM.setName** and **pM.setType** – Sergey Lotvin May 02 '16 at 21:07
  • So it sounds like you've complicated this a bit, as you're trying to determine the type on-the-fly. One critically important aspect of inheritence is that you don't want to change the class's 'duty' too far from what the parent class does. Things like `#getOccupation` would be something you'd define in an interface and apply to `Man`, rather than adding new methods you rely on in the concrete class. Additionally, you don't need to define the "setName" etc methods in the subclasses if they're just calling their super method equivalents. – Rogue May 02 '16 at 21:21
  • OK, I see, I believe. So I will try to remake my approach. Upvote for you :) – Sergey Lotvin May 02 '16 at 21:28
2

Perhaps for your study using reflection (as noted in another post) solves your problem but you want to think about your design/abstraction a little more.

As noted in the following posts:

Object Oriented Design

Downcasting is smelly

Carlos
  • 358
  • 2
  • 10
1

To do what you're trying to do, you need a variable of the right type, in order to call the right setter method.

Person pM;
switch (typeOfPerson) {
    case "Man": {
        Man man = new Man();
        man.setOccupation("military");
        pM = man;
        break;
    }
    case "Student": {
        Teenager teenager = new Teenager();
        teenager.setStdyPlace("Boston");
        pM = teenager;
        break;
    }
    default:
        // You need this, otherwise pM is not definitely-assigned below
        throw new IllegalArgumentException("Unknown type of person: " + typeOfPerson);
}
pM.setName(en);
pM.setType(tp);

However, I would suggest creating appropriate constructors to make this easier.

Person pM;
switch (typeOfPerson) {
    case "Man":
        pM = new Man(en, tp, "military");
        break;
    case "Student":
        pM = new Teenager(en, tp, "Boston");
        break;
    default:
        throw new IllegalArgumentException("Unknown type of person: " + typeOfPerson);
}
Andreas
  • 154,647
  • 11
  • 152
  • 247
0

In your example, pM is of type Person which is the 'parent' class. This field needs to be typecasted to a Man using (Man) before using the setOccupation() behavior.

You didnt give definition of Student class. However even for Student, you cannot use the setOccupation() method from the Person object because pM is just a Person reference.

  • sorry, there were misprints **Student** assumed as **Teenager** – Sergey Lotvin May 02 '16 at 21:13
  • `switch (tp){ case "Man": pM=new Man(); (Man)pM.setOccupation("military"); break; case "Teenager": pM=new Teenager(); (Teenager)pM.setStdyPlace("Boston"); break; }` this doesn't work – Sergey Lotvin May 02 '16 at 21:17