Arhn - архитектура программирования

Доступ к информации в списке абстрактного класса

У меня есть код, показанный ниже. Я создал список животных (Список ‹Животные›), в который добавил несколько кошек, собак и птиц. Можно ли получить доступ к различным полям, таким как возраст собак или окрас кошек, каждого класса непосредственно из этого списка?

Спасибо!

public abstract class Animals
{
}


public class Cat : Animals
{
    public string Name;
    public string Color;
    public int Age;
    public string Breed  
}


public class Dog : Animals
{
    public string Name;
    public string Color;
    public int Age;
    public string Breed
}

public class Bird : Animals
{
    public string Name;
    public int Age;
    public string Wing_Color;
    public string Fly_Height;
}

  • вам следует указать общие свойства в классе Animals и пометить вопрос с помощью языка программирования. 04.08.2020
  • public abstract class Animals не должно иметь множественного числа. Это должно быть public abstract class Animal. 04.08.2020

Ответы:


1

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

Да, но только если вы знаете типы во время компиляции.

C # (пока) не поддерживает правильную алгебраическую типизацию или различаемые объединения, поэтому для исчерпывающей проверки вам необходимо использовать оператор is (в идеале с пакет анализа кода, например ExhaustiveMatching) или определите свой собственный Match метод.

Вот так:

Подход 1: Использование оператора is:

Такое использование оператора is иногда называют сопоставлением с образцом, но я не согласен с этим термином, потому что на самом деле это просто эргономическое улучшение синтаксиса для проверки типов во время выполнения, а не реальное (в смысле Haskell ) сопоставление с образцом по данным.

List<Animal> animals = ...

foreach( Animal a in animals )
{
    if( a is Cat cat )
    {
        Console.WriteLine( "Cat breed: {0}.", cat.Breed );
    }
    else if( a is Dog dog )
    {
        Console.WriteLine( "Dog breed: {0}.", dog.Breed );
    }
    else if( a is Bird bird )
    {
        Console.WriteLine( "Bird name: {0}.", bird.Name );
    }
    else
    {
        throw new InvalidOperationException( "Unknown animal subclass." );
    }
}

Пакеты анализа кода, такие как ExhaustiveMatching, будут выдавать предупреждения или ошибки во время компиляции, если у вас закрыто определена иерархия типов (например, классы перечисления в стиле Java), которые вы переключаете (используя оператор C # 7.x switch с case TypeName name:-синтаксисом), но с отсутствующими подклассами.

Подход 2: Использование настраиваемого метода сопоставления / переключения:

Определение пользовательского метода Match или Switch позволяет вам требовать, чтобы используемые сайты вызовов были исчерпывающими, но это зависит от того, насколько исчерпывающим будет ваш _10 _ / _ 11_ метод, но поскольку он перекладывает бремя ответственности на вас, а не на потребителя, у этого подхода есть преимущества.

Вот так:

abstract class Animal
{
    public TResult Match<TResult>(
        Func<Cat ,TResult> isCat,
        Func<Dog ,TResult> isDog,
        Func<Bird,TResult> isBird
    )
    {
        if     ( this is Cat  c ) return isCat( c );
        else if( this is Dog  d ) return isDog( d );
        else if( this is Bird b ) return isBird( b );
        else                      throw new InvalidOperationException( "Unknown animal subclass." );
    }
}

Используется так:

foreach( Animal a in animals )
{
    String summary = a.Match(
        isCat : c => "Cat breed: " + c.Breed,
        isDog : d => "Dog breed: " + d.Breed,
        isBird: b => "Bird name: " + b.Name,
    );

    Console.WriteLine( summary );
}
04.08.2020

2

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

public abstract class Animal
{
    public string Name;
    public int Age;
    abstract string getName();
    abstract int getAge();
}


public class Cat : Animal
{
    public string Breed  
}


public class Dog : Animal
{
    public string Color;
    public string Breed
}

public class Bird : Animal
{
    public string Wing_Color;
    public string Fly_Height;
}
04.08.2020
Новые материалы

Коллекции публикаций по глубокому обучению
Последние пару месяцев я создавал коллекции последних академических публикаций по различным подполям глубокого обучения в моем блоге https://amundtveit.com - эта публикация дает обзор 25..

Представляем: Pepita
Фреймворк JavaScript с открытым исходным кодом Я знаю, что недостатка в фреймворках JavaScript нет. Но я просто не мог остановиться. Я хотел написать что-то сам, со своими собственными..

Советы по коду Laravel #2
1-) Найти // You can specify the columns you need // in when you use the find method on a model User::find(‘id’, [‘email’,’name’]); // You can increment or decrement // a field in..

Работа с временными рядами спутниковых изображений, часть 3 (аналитика данных)
Анализ временных рядов спутниковых изображений для данных наблюдений за большой Землей (arXiv) Автор: Рольф Симоэс , Жильберто Камара , Жильберто Кейрос , Фелипе Соуза , Педро Р. Андраде ,..

3 способа решить квадратное уравнение (3-й мой любимый) -
1. Методом факторизации — 2. Используя квадратичную формулу — 3. Заполнив квадрат — Давайте поймем это, решив это простое уравнение: Мы пытаемся сделать LHS,..

Создание VR-миров с A-Frame
Виртуальная реальность (и дополненная реальность) стали главными модными терминами в образовательных технологиях. С недорогими VR-гарнитурами, такими как Google Cardboard , и использованием..

Демистификация рекурсии
КОДЕКС Демистификация рекурсии Упрощенная концепция ошеломляющей О чем весь этот шум? Рекурсия, кажется, единственная тема, от которой у каждого начинающего студента-информатика..