2016-05-02 2 views
1

Я пытаюсь (изучение, как), чтобы воспользоваться преимуществами создания абстрактного класса, а затем подклассы и т.д. У меня есть суперкласс Person:Нужна помощь, чтобы понять, понижающее приведение в Java

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

и подклассы, для пример:

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(); 
    } 

} 

и подросток:

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(); 
} 

Итак, в дальнейшем я хочу делать разные действия, зависит от типа объекта. Я хотел чего-л, как:

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

Но проблема в том, рм ведут себя как Человек только. Я не могу узнать, как отбросить его на тип, который я хочу. Вопрос: как его бросить?

+0

Почему вы переопределяете геттеры и сеттеры 'name' и' type', если все, что вы делаете, это вызов 'super'? Знаете, они унаследованы. – Andreas

+0

Потому что я не знал, что не должен этого делать. Теперь я знаю - это бессмысленно. –

+0

Я считаю, что лучше (или, по крайней мере, больше [OO] (https://en.wikipedia.org/wiki/Object-oriented_programming)) способ сделать то, что вы хотите сделать, это использовать [полиморфизм] (https : //docs.oracle.com/javase/tutorial/java/IandI/polymorphism.html) вместо использования 'switch' и' instanceof' ([узнайте, почему] (https://www.google.pl/search? д = полиморфизм + против + если + еще и то есть = UTF-8 & ае = UTF-8 & gws_rd = сг & е = Nc4nV9CZCYPIsQGQ2pfgDA # д = полиморфизм + против + условными)). – TeWu

ответ

2

Используйте instanceof оператор:

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

Это говорит вам, или нет экземпляра класса является тип подкласса. Вы должны сделать это, если не знаете тип конкретного класса и хотите понизить.

+0

Я не понял эту идею. Но я ожидаю, что ** pM ** будет отличаться.Тип ** pM ** зависит от некоторой другой переменной, например ** typeOfPerson **. Я имею в виду, если это ** Человек ** Я хочу установить занятие, если ** Подросток ** есть другой метод и т. Д. Но для обоих есть ** pM.setName ** и ** pM.setType ** –

+0

Так что это похоже, что вы немного усложнили это, поскольку вы пытаетесь определить тип «на лету». Одним из критически важных аспектов наследования является то, что вы не хотите менять «долг» этого класса слишком далеко от того, что делает родительский класс. Такие вещи, как '# getOccupation', будут определяться в интерфейсе и применяться к« Человеку », а не к добавлению новых методов, на которые вы опираетесь в конкретном классе. Кроме того, вам не нужно определять методы «setName» и т. Д. В подклассах, если они просто называют их супер-эквиваленты методов. – Rogue

+0

ОК, я вижу, я верю. Поэтому я постараюсь переделать свой подход. Upvote для вас :) –

0

В вашем примере pM имеет тип Person, который является «родительским» классом. Это поле должно быть приложено к человеку, использующему (Человек), прежде чем использовать поведение setOccupation().

Вы не дали определение класса учеников. Однако даже для Student вы не можете использовать метод setOccupation() из объекта Person, потому что pM - это просто ссылка Person.

+0

извините, были опечатки ** Студент ** предполагается ** Подросток ** –

+0

'switch (tp) { case" Man ": pM = new Man(); (Человек) pM.setOccupation ("военные"); ломать; кейс "Teenager": pM = new Teenager(); (Подросток) pM.setStdyPlace ("Бостон"); ломать; } 'это не работает –

2

Возможно, ваше исследование с использованием отражения (как указано в другом сообщении) решает вашу проблему, но вы хотите немного подумать о своем дизайне/абстракции.

Как было отмечено в следующих должностях:

Object Oriented Design

Downcasting is smelly

1

Для того, чтобы делать то, что вы пытаетесь сделать, вам нужно переменную нужного типа, чтобы вызвать право метод сеттера.

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

Однако я бы предложил создать соответствующие конструкторы, чтобы сделать это проще.

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); 
} 
+0

Это именно то, что я хотел. Upvote! Но поскольку я понял, что вся архитектура не хороша, не так ли? –