2011-11-01 10 views
8

Mam dwie klasy Student i Tutor. Nauczyciel jest w zasadzie studentem (Nauczyciel przedłuża Studenta), który ma wydział ID. Po zakończeniu umowy powraca do bycia tylko studentem. Czy mogę jakoś przekonwertować go z powrotem na jego "poprzednią" rolkę ucznia?Java, czy można "przekonwertować" obiekt z podklasy do obiektu z nadklasy

+0

Możliwe, że nie powinieneś w ogóle używać dziedziczenia do modelowania tego związku. Opierając się na twoim krótkim opisie, możesz rozważyć utworzenie opakowania Tutora, które zabiera Studenta w czas budowy. Następnie, gdy umowa zostanie zakończona, możesz po prostu pozwolić, aby odwołanie do opakowania odpadło z zakresu i kontynuować pracę z instancją Ucznia bezpośrednio. –

+2

czy możesz podać nieco więcej kontekstu do swojego pytania? imho to naprawdę zależy od tego, co próbujesz osiągnąć. być może dodanie członka 'boolean isTutor;' lub po prostu trzymanie listy studentów, którzy są również nauczycielami jest wystarczające. nie ma potrzeby modelowania wszystkiego za pomocą wzorców OO tylko dlatego, że możesz. – kritzikratzi

+0

@kritzikratzi Kocham twój komentarz "Nie trzeba modelować wszystkiego z OO ... tylko dlatego, że możesz". Nie można się zgodzić na więcej! – corsiKa

Odpowiedz

5

Co naprawdę chcesz zrobić, to użyć composition and not inheritance. Zachowaj wszystkie swoje obiekty jako typ Student, a następnie tymczasowo przypisz zachowanie TutorRole, tak jak jest to wymagane do każdej instancji Student.

Za pomocą tego projektu klasa Student będzie zawierała właściwość (zmienną składową) typu TutorRole, którą można dodać lub usunąć w czasie wykonywania. Dodanie metody isTutor() pozwoli ci określić, czy Uczeń jest Nauczycielem w czasie wykonywania w sposób jasny i zwięzły.

Klasa TutorRole będzie enkapsulować zachowanie (tj. Metody) bycia Tutorem.

/* 
* The TutorRole can be set at runtime 
*/ 
public class Student { 

    private String facultyId; 

    private TutorRole tutorRole = null; 

    public boolean isTutor() { 
     return !(tutorRole == null); 
    } 

    public void doTutorStuff() { 
     if(isTutor()) { 
      tutorRole.doTutorStuff(); 
     } 
     else { 
      throw new NotTutorException(); 
     } 
    } 

    public void setTutorRole(TutorRole tutorRole) { 
     this.tutorRole = tutorRole; 
    } 
} 

/* 
* Ideally this class should implement a generic interface, but I'll keep this simple 
*/ 
public class TutorRole { 

    public void doTutorStuff() { 
     // implementation here 
    } 
} 

/* 
* Now let's use our classes... 
*/ 
Student st = new Student(); // not a tutor 
st.setTutorRole(new TutorRole()); // now a tutor 
if(st.isTutor()) { 
    st.doTutorStuff(); 
} 
st.setTutorRole(null); // not a tutor anymore 

Alternatywnym podejściem jest posiadanie klasy Tutor zawierają odniesienie do Student obiektu, ale to zależy od tego jak masz zamiar być interakcja z uczniem i Opiekun obiektów na Którędy wokół chcesz kodować ten .

2

Możesz obsadzić Nauczyciela jako studenta, więc twój kod traktuje go jako takiego w czasie kompilacji, ale obiekt pozostanie Tutorem, więc wywołanie jakichkolwiek nadpisanych metod spowoduje wywołanie wersji klasy Nauczyciela.

Jedynym sposobem na zrobienie tego rodzaju "konwersji", której szukasz, jest stworzenie nowego obiektu Ucznia i nadanie mu wszystkich właściwości, które posiada Nauczyciel.

Po stwierdzeniu, że należy wykonać tę konwersję, może zajść potrzeba ponownego przemyślenia struktury klas. Na przykład, być może zarówno Uczniowie, jak i Nauczyciele powinni naprawdę być Osobą, a każda Osoba może mieć Role Ucznia lub Nauczyciela.

+0

Czy mógłbyś to rozwinąć? Nie jestem pewien, jak to zrobić? – vedran

+0

@vedran: Jeśli chcesz edytować swoją odpowiedź, aby podać część swojego obecnego kodu i pełniejsze wyjaśnienie, co próbujesz osiągnąć, przekształcając osobę z jednego rodzaju na inną, mogę dać ci lepszą opinię. – StriplingWarrior

3

Po utworzeniu instancji pewnego typu (na przykład Tutor), jest to typ środowiska wykonawczego, który będzie mieć instancja. Tego nie można już zmienić.

Niektóre alternatywy:

  • Daj Student jakiś konstruktor, który akceptuje kolejną Student instancji i kopie nad odpowiednimi polami. Tak zwany konstruktor kopii. W ten sposób możesz łatwo utworzyć nową instancję Student na podstawie swojej Tutor, a następnie użyć jej.
  • Jeśli ważne jest, aby zachować rzeczywistą instancję zamiast tworzyć kopię (być może zachowałeś referencje w całym miejscu), najlepiej oddzielić rolę od klasy. Zrób trochę klasy FacultyMember i zmień Student i Tutor w role. Następnie możesz zmienić rolę później.
1

Nie można zmienić typów obiektów w Javie. Prawdopodobnie najłatwiejszym sposobem osiągnięcia tego jest sklonowanie wszystkich parametrów z Tutora do nowego obiektu Ucznia.

1

Możesz napisać metodę taką jak TutorToStudent() na Nauczycielu i stworzyć nowego Ucznia ze swojego Nauczyciela. Jeśli rzucisz, skończysz z tym, że obiekt wciąż jest Tutorem.

Możesz również rozważyć rezygnację z dziedziczenia w tym przypadku i po prostu mieć flagę wskazującą, czy ten uczeń jest tutorem.

+0

Ale gdybyś miał kolekcję Studentów, nadal trzymałby starego Tutora, a nie nowego zwykłego Studenta. – corsiKa

+0

@glowcoder: Prawda, ale dotyczy to większości rozwiązań, które wciąż utrzymują hierarchię dziedziczenia i próbują jakoś zmienić Nauczyciela w Studenta. Jak każde rozwiązanie, nie rozwiązuje wszystkich przypadków, a dodatkowe kodowanie będzie oczywiście wymagane w przypadku takich przypadków jak wspomniane. –

+0

Tak, to prawda, dotyczy rozwiązań, które utrzymują hierarchię dziedziczenia. Dobrą praktyką jest jednak "Przypisywanie kompozycji do dziedziczenia". Znacznie lepiej jest mieć rolę "Ucznia" i rolę "Nauczyciela" i po prostu mieć instancję (lub listę) roli (lub ról, jeśli używa się listy). – corsiKa

1
  1. Możesz utworzyć nowego Ucznia z dokładnie tymi samymi informacjami co Nauczyciel i odrzucić oryginalny obiekt. Metoda konstruktora kopii Student(Student original) lub Student toStudent() To jest szybki i brudny sposób.

  2. Zamiast Opiekun bezpośrednio rozszerzyć student dokonywania Tutor konkretnych danych i zachowania w Decorator. Albo jeszcze lepiej, uczyń zarówno dekoratory obiektu Tutor obiektu People, który obejmuje wszystkich. Jest to jeden z właściwych sposobów, aby to zrobić.

  3. Dokonać Tutor i Student w enum Type i przytrzymaj to pole w People, jest to łatwiejsze, ale mniej rozciągliwe niż wymienione powyżej, to naprawdę zależy od charakteru różnic między Nauczyciela i Ucznia.

1

Nie ma czegoś takiego jak "konwersja" go z powrotem do ucznia, jest on opiekunem, a tutor już jest studentem.

Jednak może istnieć pewna wartość w generalizacji dostępu do tego obiektu, więc używasz tylko metody ucznia. W języku Java jest kilka idiomów.

1) Możesz używać interfejsu API Studenta wyłącznie w swoim kodzie, z wyjątkiem części Nauczyciela.

2) Możesz mieć metodę "toStudent/toTutor" dla swoich obiektów, która pozwala im zwracać obiekty, które są specyficzne dla danej roli.

// Moje preferencje 3) Możesz używać interfejsów. Niech zarówno Nauczyciel, jak i Uczeń będą interfejsami i będą budować obiekty za pomocą implementacji interfejsu. Jeśli odwołasz się do obiektów używających minimalnych interfejsów, a nie do wzorców heavyweight dziedziczenia, twój kod będzie prawdopodobnie lepiej skalowany w przyszłości.

4

Myślę, że to krzyczy, powstrzymywanie i programowanie interfejsu.

Jak o tym:

interface IStudent 
{ 
    String getName(); 
    int getStudentId(); 
} 

interface IFacultyMember 
{ 
    int getFacultyId(); 
} 

class Student 
    implements IStudent 
{ 
    String name; 
    int id; 

    public String getName() { return name; } 
    public int getStudentId() { return id; } 
} 

class Tutor 
    implements IStudent, IFacultyMember 
{ 
    Student student; 
    int facultyId; 

    public Tutor (Student student, int facultyId) 
    { 
    this.student = student; 
    this.facultyId = facultyId; 
    } 

    public String getName() { return student.getName(); } 
    public int getStudentId() { return student.getStudentId(); } 
    public int getFacultyId() { return facultyId; }; 
} 

ten sposób swoją Student pozostaje student, nawet jeśli porusza się w pozycji nauczyciela. Kiedy kończy się okres Tutora, po prostu GC jest rekordzistą nauczyciela.

Z drugiej strony, zapisy studentów nadal będą dostępne w Centralnych Usługach.

Powiązane problemy