Как правильно использовать абстрактный базовый класс C # - PullRequest
1 голос
/ 16 марта 2012

Привет! Я создаю библиотеку геометрии в C # ...

У меня есть форма абстрактного класса.Я определил вектор класса (также представляющий (x, y) точки).

Я хотел бы использовать различные геометрические объекты, кривые, линии, дуги, пути и т. Д.

.это я определил абстрактный класс Segment и вывел ряд классов, например LineSegment (см. ниже), CurveSegment, ArcCircleSegment, BezierCurveSegment, HalfInfiniteLine и т. д.

IМы также определили класс Path (НЕ абстрактный), который предназначен для представления нескольких сегментов, соединенных вместе (например, что вы можете получить из приложения для рисования).В это я включаю член List сегментов (List<Segment>).

Затем я хочу получить классы из Path, ключевым примером является LinePath, который должен содержать только LineSegments.У меня проблема в том, что я хотел бы иметь возможность вызывать свойство get для LinePath объекта, предполагая, что он вернет LineSegment.Возможно ли это без явного приведения каждый раз?

Я хочу не делать абстрактным Path, поскольку у меня может быть путь нескольких типов сегментов.

public class LineSegment : Segment 
{
    private vector m_start;
    private vector m_end;
    private vector m_vector;

    public vector Start
    {
        get { return m_start; }
        set { m_start = value; }
    }

    public vector End
    {
        get { return m_end; }
        set { m_end = value; }
    }

    public vector Vec
    {
        get { return m_vector; }
        set { m_vector = value; }
    }

    public double Length()
    {
        return Vec.length();
    }

    public LineSegment(vector v0, vector v1):base()
    {
        this.Start.x = v0.x;
        this.Start.y = v0.y;
        this.End.x = v1.x;
        this.End.y = v1.y;

        this.Vec = this.End - this.Start;
    }
}

Ответы [ 3 ]

2 голосов
/ 16 марта 2012

Если я правильно понимаю, что вы хотите, вы можете сделать что-то вроде этого:

Сделать свой класс пути общим

public class Path<T> where T : Segment
{
    private IList<T> segments = new List<T>();

    public IList<T> Segments { get { return this.segments; } }
}

Затем вы можете создать свой объект LinePath

public class LinePath : Path<LineSegment>
{
}

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

0 голосов
/ 16 марта 2012

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

Например, снова возьмем пример Vehicle.класс выше.Если мы хотим, чтобы все классы, производные от Vehicle, реализовали метод Drive () фиксированным способом, тогда как другие методы могут быть переопределены дочерними классами.В таком сценарии мы реализуем класс Vehicle как абстрактный класс с реализацией Drive, а другие методы / свойства оставляем абстрактными, чтобы они могли быть переопределены дочерними классами.

-> Цельабстрактный класс должен предоставлять общее определение базового класса, который может совместно использоваться несколькими производными классами.

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

Используйте абстрактный класс

When creating a class library which will be widely distributed or reused—especially to clients, use an abstract class in preference to an interface; because, it simplifies versioning. This is the practice used by the Microsoft team which developed the Base Class Library. ( COM was designed around interfaces.)

Use an abstract class to define a common base class for a family of types.

Use an abstract class to provide default behavior.

Subclass only a base class in a hierarchy to which the class logically belongs.
0 голосов
/ 16 марта 2012

Вы можете переопределить свойство Path для ваших производных классов.LinePath может иметь:

public new List<LineSegment> Segments 
{
    get
    {
        return (List<LineSegment>)base.Segments;
    }
}

Таким образом, вы обеспечите правильное использование типа.

...