2016-03-22 18 views
0

ich OOP in C# lernen jedoch Schwierigkeiten, eine Mock-Anwendung entwerfen, die ein Universität Kartensystem simuliert die Schüler und Mitarbeiter bestimmte Dienste/Gebäude zugreifen kann.OOP-Schnittstellen und abstrakte Klassen

enter image description here

Ich habe eine abstrakte Klasse UniversityMember, die Informationen enthält, die für jeden Schüler commons wie jeder hat ein Vorname usw. Ich habe Schnittstellen, die spezifischer sind wie IStudent erzeugt studentIds und stellen Tür/Zugriffsebene ist Verwenden der enum AccessLevel-Klasse. Allerdings, wenn ich

public static void Main(string[] args) 
{ 
    Student Majid = new Student(); 

    Majid.FName = "foo"; 
    Majid.LName = "hello"; 
    Majid.SetStudentId(); 
    Majid.ExpiryDate = new DateTime(2018, 09, 10); 
    Majid.Type = MemberType.Student; 

    Majid.setStudentLevel(AccessLevel.CharlesWilson, 
          AccessLevel.ComputerScienceBuilding, 
          AccessLevel.DavidWilson); 

    PayTutionFees(Majid); 
} 

public static void PayTutionFees(IStudent student) 
{ 
    //Design problem 
    //student.ID etc 
} 

verwende ich Polymorphismus, weil jeder Schüler implementiert IStudent aber ich habe nicht den Zugang zu den Informationen für Studenten als in der abstrakten Klasse UniversityMember entfernt. Ich möchte nicht, dass die Schnittstellen mit wiederholten Methoden gefüllt werden, da es sich um gemeinsame Informationen zwischen Schülern und Lehrern handelt. Wie kann ich dieses Problem umgehen?

+2

Ich sehe keine Klassen als 'Student', die' ISstudent' implementieren und ich nehme an, nur Studenten zahlen Gebühren. Vielleicht könnten Sie den Parametertyp für 'Student' ändern? – Michael

+0

Okay, aber was, wenn ich eine Methode wollte, die nur GymMembers erlaubt, benutzen Schüler und Angestellte beide das Gym-Interface, wie würde ich das machen? – dijam

+0

Ihr Parameter ist IStudent und es gibt keine ID-Eigenschaft auf IStudent. Also '(Student) student.ID' würde funktionieren. Oder 'Student als Student'. Um falsches Casting zu verhindern, können Sie mit 'if (student.GetType() == typeof (Student))' oder 'student is Student' nachsehen –

Antwort

3

könnte acces Wenn Sie wissen, dass die Implementierer von IStudent, IWorkingStaff usw. gemeinsam einige Eigenschaften haben, Sie können diese in einer separaten Schnittstelle beschreiben, z. B. IUniversityMember:

public interface IUniversityMember 
{ 
    String ID {get;} 
    // etc. 
} 

Und machen Sie Ihre bestehenden Schnittstellen, die Zugriff auf diese gemeinsamen Eigenschaften implizieren, erweitern IUniversityMember.

public interface IStudent : IUniversityMember {...} 
public interface IWorkingStaff : IUniversityMember {...} 

(was bedeutet, dass beide IStudent und IWorkingStaff jetzt ihre Implementierer erfordern Eigenschaften, aufgeführt in IUniversityMember Schnittstelle zusätzlich zu ihren eigenen.) Dann können Sie Ihre abstrakten UniversityMember Klasse diese neue IUniversityMemeber Schnittstelle machen implementieren.

Da Ihre konkreten Klassen sowieso UniversityMember sind, werden sie diese breitere Schnittstelle automatisch erfüllen, da sie alle von IUniversityMember geforderten Eigenschaften von ihrer abstrakten Basisklasse geerbt haben.

Auf diese Weise können Sie IStudent als Parameter in Ihrer Methode akzeptieren und haben weiterhin Zugriff auf Eigenschaften, die es mit anderen Arten von Universitätsmitgliedern gemeinsam hat.

1

Wenn Sie die Schnittstelle als Parameter verwenden, können Sie student.ID nicht verwenden, da Sie nicht sicher sein können, dass nur die Klasse Student die angegebene Schnittstelle implementiert. Sie sollten sich nur auf Schnittstellenmitglieder verlassen. In diesem Fall nehme ich an, dass Sie nur den falschen Parametertyp verwenden (wie ich in meinem Kommentar erwähnt habe).

1

Das Problem ist, dass Sie nicht eine Abstraktion von der Implementierung trennte sich. Wenn Sie mehr generic-wie Informationen, die für alle Mitglieder, dann sollten Sie es in einer Schnittstelle deklarieren, zB:

public interface IUniversityMember 
{ 
    publis string Name {get;set;} 
    publis string Id {get;set;} 
} 

und erben es dann in Ihrer IStudent Schnittstelle:

public interface IStudent: IUniversityMember 
{ 
    publis string StudentRelatedProperty {get;set;} 
} 

während UniversityMember Klasse sollte die IUniversityMember implementieren. Eine abstrakte Klasse ist ein Implementierungsdetail, das nicht verfügbar gemacht werden sollte.

1

Sie versuchen IStudent.ID

public static void PayTutionFees(IStudent student) 
{ 
    student.ID // at this point student is a IStudent so no ID prop available 
} 

Sie beginnen an dieser Stelle Casting

public static void PayTutionFees(IStudent student) 
{ 
    //Design problem 
    (Student)student.ID; 
    var realStudent = student as Student; 

    //to avoid wrong cast check for type before 

    if(student.GetType() == typeof(Student)) 
    {//jippy student is a Student!} 
} 
Verwandte Themen