В языках, не позволяющих использовать свободные функции (free-standing functions), приходится заменять их методом класса. При этом метод может быть статическим или нет, а в последнем случае аргумент может передаваться конструктору или методу. Что влияет на выбор одной из этих альтернатив?
class Utility
{
public static int Increment(int i) { return i + 1; }
}
class Increment
{
private int value;
public Increment(int i) { value = i + 1; }
public int Value() { return value; }
}
class Incrementer
{
public Incrementer() { }
public int Increment(int i) { return i + 1; }
}
Здравствуйте, igna, Вы писали:
I>В языках, не позволяющих использовать свободные функции (free-standing functions), приходится заменять их методом класса. При этом метод может быть статическим или нет, а в последнем случае аргумент может передаваться конструктору или методу. Что влияет на выбор одной из этих альтернатив?
Ну, конечно же, статический метод класса, для того они и есть. А ещё бывают полностью статические классы, объединяющие семейство таких функций. Если нужно смоделировать замыкания (это только на уровне private-методов), то тут стоит написать не статический класс, где в конструктор передавать контекст, если, конечно, этот контекст велик (иначе, можно просто без всяких замыканий таскать контекст в параметрах). Если семейство алгоритмов зависит от каких-то параметров, то их можно реализовать в виде нестатических методов, но, собственно, так мы уже уходим от понятия "свободная функция" и приходим к нашим любимым методам.
Здравствуйте, igna, Вы писали:
I>В языках, не позволяющих использовать свободные функции (free-standing functions), приходится заменять их методом класса. При этом метод может быть статическим или нет, а в последнем случае аргумент может передаваться конструктору или методу. Что влияет на выбор одной из этих альтернатив?
Чаще всего при выборе между тем, сделать ли функцию свободной или членом класса я руководствуюсь следующим: если эта ф-я должна доступаться к объекту только посредством его открытых членов и/или свободные функций, то делаю ф-ю свободной. Иначе делаю ее членом класса.
Здравствуйте, igna, Вы писали:
I>В языках, не позволяющих использовать свободные функции (free-standing functions), приходится заменять их методом класса. При этом метод может быть статическим или нет, а в последнем случае аргумент может передаваться конструктору или методу. Что влияет на выбор одной из этих альтернатив?
I>
I>class Utility
I>{
I> public static int Increment(int i) { return i + 1; }
I>}
I>
Это означает, что у тебя есть ровно одна реализация этой функции. В языках, которые не поддерживают концепции "указатель на метод", такой инкремент нельзя использовать в косвенном стиле. Хотя это можно обойти подходящим средством-заменителем для согласования сигнатур (например, анонимным классом в Java).
I>
I>class Increment
I>{
I> private int value;
I> public Increment(int i) { value = i + 1; }
I> public int Value() { return value; }
I>}
I>
Довольно-таки редкая конструкция. Как правило, используется в значительно более сложных случаях, для компенсации неизменяемости объектов с value-семантикой. См. напр. StringBuilder и UriBuilder в .Net.
I>
I>class Incrementer
I>{
I> public Incrementer() { }
I> public int Increment(int i) { return i + 1; }
I>}
I>
Эта конструкция применяется в тех случаях, когда подразумевается возможность выбора из нескольких алгоритмов или реализаций одного алгоритма. Для инкрементера это выглядит странным, но если взять случай поинтереснее, все станет понятным:
public interface ITrigonometry;
{
double Sin(double angle);
double Cos(double angle);
}
public class FPUTrigonometry : ITrigonometry; // Provides the default trigonometry operations built over the FPUpublic class FastTrigonometry : ITrigonometry; // performs fast fixed-point table-based lookups with limited precision.
Примеры реального боевого применения можно посмотреть в System.Text.Encoding.
1.2.0 alpha rev. 655
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Андрей Коростелев, Вы писали:
АК>Чаще всего при выборе между тем, сделать ли функцию свободной или членом класса я руководствуюсь следующим: если эта ф-я должна доступаться к объекту только посредством его открытых членов и/или свободные функций, то делаю ф-ю свободной. Иначе делаю ее членом класса.
Ага. А как быть, если нужно на Java/C# написать метод там, где на C++ ты написал бы свободную функцию?
Здравствуйте, igna, Вы писали:
I>Здравствуйте, Андрей Коростелев, Вы писали:
АК>>Чаще всего при выборе между тем, сделать ли функцию свободной или членом класса я руководствуюсь следующим: если эта ф-я должна доступаться к объекту только посредством его открытых членов и/или свободные функций, то делаю ф-ю свободной. Иначе делаю ее членом класса.
I>Ага. А как быть, если нужно на Java/C# написать метод там, где на C++ ты написал бы свободную функцию?
Засунуть ее в класс Util. Util сделать абстрактным и с приватным конструктором, дабы никто не отнаследовался.
Здравствуйте, Gajdalager, Вы писали:
I>>Ага. А как быть, если нужно на Java/C# написать метод там, где на C++ ты написал бы свободную функцию?
G>Засунуть ее в класс Util. Util сделать абстрактным и с приватным конструктором, дабы никто не отнаследовался.
А в C# 2.0 — просто статическим.
What a piece of work is a man! how noble in reason! how infinite in faculty! in form and moving how express and admirable! in action how like an angel! in apprehension how like a god! the beauty of the world! the paragon of animals!
I>class Utility
I>{
I> public static int Increment(int i) { return i + 1; }
I>}
I>
Процедурное программирование. Хорошо это или плохо — не важно, но вступает в противоречие с subj Плюс статическое связывание. Легко приводит к не возможности unit-тестирования. Тогда приходится тестировать всю программу целиком. Единственное применение, которое я вижу, это так ложить небольшие функции, которые нельзя положить в правильное место, из-за ограничений хост-платформы. То есть, если функция должна лежать в классе String или Number (как в твоём примере), но туда её всунуть мы не можем, то пихаем в статический утилитный класс.
I>
I>class Increment
I>{
I> private int value;
I> public Increment(int i) { value = i + 1; }
I> public int Value() { return value; }
I>}
I>
Именно в таком виде — это жесть
I>
I>class Incrementer
I>{
I> public Incrementer() { }
I> public int Increment(int i) { return i + 1; }
I>}
I>
Если нужен патерн Стратегия, то таки так. Нужна она может быть как самой программе, так и для нужд тестирования (деланья моков). С другой стороны, если такого кода много, то это явный признак процедурного подхода.