2012-06-27 4 views
3

Я недавно начал изучать C# и столкнулся с проблемой. Я не очень хорошо разбираюсь в абстрактных/интерфейсных классах, но понимаю основные принципы и приложения.Передача абстрактного класса в качестве аргумента в методе

Я сейчас смотрю ООП для C#. Я уже знаю механику ООП, выполнив ее на Java, но так и не использовал абстрактные или интерфейсные классы.

Цель моего кода - передать в ArrayList объектов (оба ребенка общего родительского класса) и распечатать только те объекты, которые принадлежат к данному классу. Это работает, но мне было любопытно посмотреть, могу ли я получить тот же метод для печати всех дочерних объектов родительского класса, если родительский класс является абстрактным.

Родитель Класс

abstract class Person 
{ 
    protected string Name { get; set; } 
    protected int Age { get; set; } 

    public override string ToString() { return "Person:" + Name + ", " + this.Age; } 
} 

Детский класс

class Student : Person 
{ 
    private int studID { get; set; } 
    private string school { get; set; } 
    public Student() { } 
    public Student(string name, int age, int studID, string school) 
    { 
     this.Name = name; 
     this.Age = age; 
     this.studID = studID; 
     this.school = school; 
    } 

    public override string ToString() 
    { 
     string s = "Student:" + Name + ", " + Age + ", " + studID + ", " + school; 
     return s; 
    } 
} 

Метод вызова

private static void StudentDetails(object type) 
    { 
     ArrayList tmp = new ArrayList(); 
      //display all 
      //foreach (Person p in people) tmp.Add(p); 
      foreach (Person p in people) 
      { 
       if (type.GetType() == p.GetType()) 
       { 
        tmp.Add(p); 
       } 
      } 
      //etc... 
+1

Вы знаете тип во время компиляции? –

ответ

1

Не сравнивайте GetType(), потому что он не проверяет наследование и прочее. Проверьте метод IsAssignableFrom ->http://msdn.microsoft.com/de-de/library/system.type.isassignablefrom.aspx, это то, что вы ищете.

+0

Спасибо, Это именно то, что я искал. Отлично работает при реализации с обновленным методом StudentDetails (тип типа), рекомендованным nawfal. – hamhut1066

+0

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

0

Вы можете сделать может быть что-то вроде:

Не используйте ArrayList, но используйте IEnumerable<Person> в этом случае, так как все объекты производны от Person абстрактного класса.

private static void StudentDetails(Type filter) 
{ 
    var filteredTypes = people.Where(p=>p.GetType() == filter);    
    .... 
} 
1

Если вы знаете тип во время компиляции вы можете использовать:

private static void StudentDetails<T>() 
{ 
    ArrayList tmp = new ArrayList(); 
    foreach (Person p in people) 
    { 
     if (p is T) 
     { 
      tmp.Add(p); 
     } 
    }    
} 

Позвони

StudentDetails<Student>(); 

Некоторые мысли:

  1. Вы должны изменить ArrayList к чему-то более сильно напечатано как List<T>. В вашем случае List<Person>.

  2. Дайте StudentDetails лучшее именование. Имя метода должно быть глаголом.

1

Если вы знаете тип во время компиляции, вы можете сделать это:

var students = people.OfType<Student>().ToList(); 

И полностью избавиться от метода StudentDetails. OfType<T> документация может быть найдена here.

Я не уверен в этом, но это может также получить типы, которые получены от T (в моем примере, полученном от Student). Вызов ToList() необходим только в том случае, если вам нужен List<T>, а не IEnumerable<T>.

Если Type аргумент определяется во время выполнения, это решение будет не работы в качестве дженериков требуется время компиляции разрешение типов, подлежащего кодированию, как это.

0

Вы можете сделать это просто отлично, используя базовый класс (хотя это абстрактное):

class Program 
{ 
    static void Main(string[] args) 
    { 
     List<Person> persons = new List<Person>(); 

     persons.Add(new Student("John", 18, 1, "Stanford")); 
     persons.Add(new Student("Matt", 20, 2, "Stanford")); 
     persons.Add(new Teacher("Alice", 30)); 

     StudentDetails(persons); 
    } 

    private static void StudentDetails(List<Person> people) 
    { 
     foreach (Person p in people) 
     { 
      try 
      { 
       Student s = (Student)p; 
       Console.WriteLine(s.ToString()); 
      } 
      catch(InvalidCastException e) 
      { 
      } 
     } 
    } 
} 
-1

Прежде всего:

Основной отличается между интерфейсом и абстрактным классом, что вы можете написать методы в базе, чтобы обеспечить поведение по умолчанию для вашего кода. Как известно, это невозможно в интерфейсе, потому что здесь u предоставляет только сигнатуры метода.

Образец, предоставленный вами, немного сомнителен, для таких реализаций вы действительно используете простые базовые классы и не абстрактные классы. Чтобы предоставить коллекцию или поле вашего базового типа, вам нужно использовать базу, которая может быть создана, что не разрешено абстрактным классом.

Теперь ваш вопрос:

Давайте подумаем это корыто. Вы хотите иметь базовый объект, который не может быть установлен, но вы хотели бы предоставить коллекцию этого класса ... Вы видите проблему. Если вы действительно хотите это сделать, будет много способов проверки и проверки типов, но при этом вся идея не имеет смысла. Лучшим способом будет реализация интерфейса, но с этим вы не сможете обеспечить поведение по умолчанию!

Мое предложение:

Для вашего образца использовать обычный класс Person и пусть Student Наследовать от него. Вы по-прежнему используете свой метод ToString по умолчанию и переопределяете его в классе Student. Для будущего кода. Подумайте, если вы: нужны экземпляры вашей базы (коллекции, картины и т.д.) -> Простая база или интерфейс

потребность поведение по умолчанию и экземпляры -> Простая база

не нужны экземпляры поведения NO по умолчанию -> Интерфейс

поведение по умолчанию необходимо NO экземпляры -> абстрактный

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

НТН

Christoph

+0

Наличие коллекции, набранной для абстрактного базового класса, не является проблемой вообще, и она не требует никаких проверок или проверки типов. –