Обработка функций с одинаковой подписью, но разными значениями параметров - PullRequest
0 голосов
/ 30 октября 2018

Я читал Чистый код Роберта С. Мартина. В нем он заявляет, что функция должна использовать минимальное количество параметров по мере необходимости, и что имена функций должны соответствовать соглашению об именах в рамках всего проекта, избегая при этом беспричинного контекста.

Например, если у меня есть простой класс, который я написал для этого вопроса, Car:

public class Car
    {
        internal string make { get; set; }
        internal string model { get; set; }

        public Car(string make, string model)
        {
            this.make = make;
            this.model = model;
        }
    }

А класс Cars:

public class Cars
{
    internal List<Car> cars { get; set; }

    public Cars(List<Car> cars)
    {
        this.cars = cars;
    }

    public Car GetCar(string make)
    {
        foreach (Car car in cars)
        {
            if (car.make == make) return car;
        }
        return null;
    }

    public Car GetCar(string model)
    {
        foreach (Car car in cars)
        {
            if (car.model == model) return car;
        }
        return null;
    }

}

Очевидно, что это не компилируется, так как функции с именем GetCar имеют одинаковую сигнатуру функции.

Обычно я мог бы обойти это, переименовав функции GetCarByMake и GetCarByModel, или что-то подобное, но текст, кажется, указывает, что это не лучшая практика. В других случаях я мог бы добавить дополнительный неиспользуемый параметр для их дифференциации.

Моей следующей мыслью было создание класса для каждого свойства в Car; есть класс для Make и Model, который содержит строковое свойство. Однако, это, кажется, приводит к ненужным накладным расходам.

Мне любопытно, как я могу реализовать / назвать несколько функций, которые выполняют условно похожие вещи, имеют одинаковые типы данных параметров и выводят один и тот же тип данных, не имея разных имен функций? Кроме того, меня не интересует перегрузка дополнительных функций или полиморфизм для этого вопроса или подобные темы; Я хочу знать ответ относительно классов, поскольку они в настоящее время без существенных изменений. Единственный ответ, который я сейчас вижу, - это создание классов для каждого свойства.

Пожалуйста, дайте мне знать, если необходимы какие-либо разъяснения или изменения.

EDIT: Так же, как некоторая дополнительная информация, это чисто академическое упражнение. Профессионально, я бы просто создал методы с разными именами и покончил бы с этим. Как указано в комментариях, это просто, ремонтопригодно и работает.

Ответы [ 2 ]

0 голосов
/ 31 октября 2018

Можно иметь несколько методов с одним и тем же «именем» и сигнатурой в одном классе с помощью явной реализации интерфейса:

public interface IFindByMake
{
     Car GetCar(string make);
}

public interface IFindByModel
{
     Car GetCar(string model);
}

public class Cars : IFindByMake, IFindByModel
{
    internal List<Car> cars { get; set; }

    public Cars(List<Car> cars)
    {
        this.cars = cars;
    }

    Car IFindByMake.GetCar(string make)
    {
        foreach (Car car in cars)
        {
            if (car.make == make) return car;
        }
        return null;
    }

    Car IFindByModel.GetCar(string model)
    {
        foreach (Car car in cars)
        {
            if (car.model == model) return car;
        }
        return null;
    }
}

Приведенный выше код компилируется; однако вы заметите, что если вы объявите переменную типа Cars, метод GetCar не будет доступен. Вы можете вызвать метод, только если вы приведете к одному из двух типов интерфейса или объявите переменную как один из двух типов.

var cars = new Cars();
((IFindByMake)cars).GetCar(“Ford”);

Или

IFindByModel cars = new Cars();
cars.GetCar(“Mustang”);

Иначе как компилятор узнает, какой метод вызывать?

0 голосов
/ 31 октября 2018

Вы можете использовать linq, как указано ниже

public Car GetCar(string make, string model)
{

    return cars.Where(w=>  (string.IsNullOrEmpty(make) || w.make == make) &&(string.IsNullOrEmpty(model) || w.model == model)).Select(s=>s).FirstOrDefault();
}
...