Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Системный анализ, проектирование и UML > Наследование: линия, луч, сегмент


Автор: zlobozavr 14.12.2008, 15:48
Такая вот задачка, хотелось бы знать Ваше мнение. Рассмотрите три геометрических понятия: линия (бесконечна в обоих направлениях), луч (начало в фиксированной точке, бесконечен в одном направлении), сегмент (отрезок прямой с фиксированными концами). Как бы вы построили классы, представляющие эти три понятия, в виде иерархии наследования? Будет ли ваше решение другим, если вы обратите особое внимание на представление данных (на поведение)? Охарактеризуйте тип наследования, который вы использовали. 

Насколько понимаю, изменится. Базовый класс - линия. Его наследует луч, а его сегмент. Но при рассмотрении поведения, например, НАРИСОВАТЬ, здесь уже композиция - сегмент содержится в луче, а луч в линии.. Или я не прав?

Автор: deniva 14.12.2008, 21:41
Пример может быть не очень хорош, но суть понятна.

Решение - образец проектирования Bridge

Автор: zlobozavr 14.12.2008, 21:59
thnx, только никогда не использовал его...

Автор: maxim1000 14.12.2008, 22:33
никакого наследования в смысле ООП тут нет

луч не является отрезком, отрезок не является лучом, с прямой - то же самое


чтобы обратить внимание на поведение, нужно знать, что ж у них за поведение - в разных системах можно дать разный набор операций

Автор: zlobozavr 14.12.2008, 22:40
Как нет наследования?
Код

    class MyLine
    {
        protected Double angle;
        public MyLine(double ang)
        {
            angle = ang;
        }
        public virtual void DrawMyLine(Graphics gr)
        {  
            double x = Math.Cos(angle) * 500;
            double y = Math.Sin(angle) * 500;
            gr.DrawLine(Pens.Black, 0, 0, (float)x, (float)y);
        }
    }

    class MyRay : MyLine
    {
        protected PointF start;
        public MyRay(double ang, PointF strt) : base(ang)
        {
            start = strt;
        }
        public override void DrawMyLine(Graphics gr)
        {
            double x = Math.Cos(base.angle) * 500;
            double y = Math.Sin(base.angle) * 500;
            gr.DrawLine(Pens.Black, start.X, start.Y, (float)x, (float)y);
        }
    }

    class MySegment : MyRay
    {
        double length;
        public MySegment(double angl, PointF st, double len) : base(angl, st)
        {
            length = len;
        }
        public override void DrawMyLine(Graphics gr)
        {
            double x = Math.Cos(base.angle) * length;
            double y = Math.Sin(base.angle) * length;
            gr.DrawLine(Pens.Black,base.start.X, base.start.Y, (float)x, (float)y);
        }
    }


 А поведение ну хотя бы самый элементарный случай - Нарисовать()

Автор: maxim1000 15.12.2008, 09:42
Цитата(zlobozavr @  14.12.2008,  22:40 Найти цитируемый пост)
Как нет наследования?

smile
конечно, можно написать программу, где одно наследуется от другого
но, насколько я понял, интересует, как написать её правильно
наследование в ООП выражает знание о том, что все объекты какого-то класса также являются объектами более общего класса (классический пример: любое яблоко является фруктом)
так вот в данном случае это не так - луч не является прямой

Добавлено через 1 минуту и 30 секунд
а что касается поведения:
в данном случае можно выделить базовый класс "объект, который можно нарисовать" и все класса унаследовать от него

Автор: mes 15.12.2008, 09:50
Код

class Figure 
{
   public:
     virtual void  Draw (DC& );  
};

class FgRay : public Figure
{
   public:
     virtual void  Draw (DC& dc)
    {
          ..
          dc.Draw...
    }  
   private:
     Point  m_Start;
};

class FgLine : public Figure
{
   public:
     virtual void  Draw (DC& dc)
    {
          ..
          dc.Draw...
    }
  private:
     Point  m_Start, m_End;
};

class FgSegment : public Figure
{
   public:
     virtual void  Draw (DC& dc)
    {
          ..
          dc.Draw...
    }  
  private:
     Point  m_Start;
     Angle  m_Angle;
};

Автор: zlobozavr 15.12.2008, 10:18
Луч является прямой. Луч - это часть бесконечной прямой у которой есть только одно отличие - начало. Луч наследует у прямой - угол и добавляет координаты точки начала луча. Разве нет?

Автор: ida 15.12.2008, 10:24
zlobozavr, вы лучше задачу опишите.
Все зависит от того, как мы потом собираемся работать с этим лучом, отрезком и тп.
Что хорошо для одних задач, будет плохо для других. Типичная программерская ошибка - отбрасывать предметную область.

Автор: ksili 15.12.2008, 10:25
Цитата(zlobozavr @  15.12.2008,  14:18 Найти цитируемый пост)
Луч является прямой

и
Цитата(zlobozavr @  15.12.2008,  14:18 Найти цитируемый пост)
Луч - это часть бесконечной прямой

это разные вещи.

По вашему, глаз является частью человека, следовательно, глаз - это человек!
maxim1000, выше все верно написал

Автор: zlobozavr 15.12.2008, 11:35
Это небеизвестная книга: Бадд Объектно-ориентированное программирование в действии, 7.6.4

Автор: ida 15.12.2008, 11:40
zlobozavr, не поняла ответа.
Вы просто тренируетесь? Никакой прикладной цели нет?

Автор: zlobozavr 15.12.2008, 13:44
Пока да. smile 

Автор: ida 15.12.2008, 15:22
Тогда я вам отвечу. 
Решение полностью определяется задачей. Не зная задачи, нельзя построить оптимальную модель. Т.к. решений здесь множество, каждое подойдет, но надо знать, в какой ситуации его применять.

Автор: zlobozavr 15.12.2008, 15:42
Согласен. Именно поэтому и обратился за помощью потому как нашел несколько вроде казалось правильных решений, подумал что запутался...

Автор: zlobozavr 15.12.2008, 16:01
mes

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

Автор: ida 15.12.2008, 16:28
Все зависит от системы координат.
Можно взять декартову, а можно полярную.
Тогда в декартовой всем трем будет достаточно двух точек
А в полярной - угла и одной точки.

Автор: zlobozavr 15.12.2008, 17:06
тоже верно  smile 

Автор: maxim1000 15.12.2008, 19:13
Цитата(zlobozavr @  15.12.2008,  16:01 Найти цитируемый пост)
по поводу твоей реализации, дело в том что угол нужен всем трем, точка начала нужна только двум, а точка конца только одному из трех перечисленных объектов.

можно выделить класс объектов, которые могут быть аналитически представлены частью прямой
что-то типа Linear

границы можно будет задавать параметром на этой прямой, а не полноценными трёхмерными точками, у прямой не будет ни одной, в луча одна, у отрезка - две границы

от этого класса унаследуются все три объекта

хотя здесь стоит быть поосторожнее - получается вынесение внутренних аспектов реализации наружу

Автор: zlobozavr 15.12.2008, 20:19
Интересный вариант..  smile 

Автор: StepS 16.12.2008, 19:44
maxim1000, практически прав, но я бы предложил немного другой подход:

все три объекта содержат координаты хотя бы 2-х точек, т.к. чтобы нарисовать линию - нужно знать 2 точки, луч - тоже, только у него одна из точек является началом, отрезок - 2 точки (начало и конец). Т.е. у них разное только поведение НарисоватьСебя. Отсюда имеем:

Код

class Line {
private Point x, y;
public Draw(){
   //уравнение прямой
}

class Ray:Line {
  public new Draw(){
     //уравнение прямой, но начало отсчета по x координате берется из приватной переменной
  }
}

class Segment: Line {
  public new Draw(){
     //уравнение прямой, но ограничение идет по 2-м точкам.
  }
}


как-то так.

Автор: zlobozavr 16.12.2008, 20:18
аналогично как и я думал сначала. Но дело в том что не требуется здесь никакая конкретная реализация, а
    
1. Как бы вы построили классы, представляющие эти три понятия, в виде иерархии наследования? 
2. Будет ли ваше решение другим, если вы обратите особое внимание на представление данных (на поведение)? 
3. Охарактеризуйте тип наследования, который вы использовали.

По-моему правильнее будет

1. сегмент - часть луча, луч - часть линии ("has a")
2. не изменится (нарисоватьСебя())
3. композиция

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)