Как обрабатывать один и тот же путь кода с разными параметрами?

Я столкнулся с ситуацией, когда, пытаясь не изменять базовый исходный код (это не совсем "мой" код на этом уровне; в противном случае я хотел бы изменить его), у меня есть два почти идентичных пути кода, но с отдельные типы данных, которые я использую.

Не обращая внимания на то, что вы, вероятно, можете довольно легко преобразовать одно в другое, похожим примером будет объект "Круг".

С одной стороны, у меня есть Point объект и радиус. С другой стороны, у меня есть Circle объект. Оба они могут описывать один и тот же фактический круг, но я просто не могу преобразовать один в другой.

Тогда в моем коде у меня есть:

void Run(Circle circle)
{
    if(AllNegative(circle))
    {
        // ...
        // Do unrelated stuff
        // ...
        ColorCircle(circle);
        // ...
    }
}

void Run(Point pt, uint radius)
{
    if(AllNegative(pt, radius))
    {
        // ...
        // Do unrelated stuff
        // ...
        ColorCircle(pt, radius);
        // ...
    }
}

bool AllNegative(Circle circle) { return (circle.AllNegative); }
bool AllNegative(Point pt, uint radius) { return ((pt.X + radius) < 0) && ((pt.Y + radius) < 0); }

void ColorCircle(Circle circle) { /* ... */ }
void ColorCircle(Point pt, uint radius) { /* ... */ }

Конечно, у меня есть больше кода в Run чем в этом примере.

Как мне слить Run в одну функцию, чтобы минимизировать дублирование кода?

4 ответа

Решение

В этом случае вы можете выбрать два пути:

  1. Вы можете оставить все как сейчас - перегруженные методы.
  2. Переместить дублированный код в новый метод. Если в вашем unrelated В разделе вы рассчитываете диаметр круга (реалистичный или нет), создаете метод calcDiameter(radius),

В такой ситуации нет ничего плохого с дублированным кодом, если только пара строк действительно не делает новый метод практичным.

Пример с дженериками:

public interface ICircle
{
    Point Point{get;}
    uint Radius{get;}
    ... add whatever you need
}

public class MyCircle: ICircle
{
   private Circle _circle;
   ... implement interface
}

public class MyCircle2: ICircle
{
   private Point _point;
   private uint _radius;
   ... implement interface
}

void Run<T>(T circle) where T: ICircle
{
    if(AllNegative(circle))
    {
        ColorCircle(circle);
    }
}

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

public interface IMyShape
{
    public bool IsNegative();
    public void Color();
}

Тогда вам понадобится только один метод, который принимает ссылку IMyShape:

void Run(IMyShape shape)
{
    if(shape.AllNegative())
    {
        // ...
        // Do unrelated stuff
        // ...
        shape.Color();
        // ...
    }
}

Как минимум, вы могли бы сделать unrelated stuff в отдельном методе и вызывать его из каждого Run,

Другие вопросы по тегам