Страницы

Поиск по вопросам

четверг, 19 декабря 2019 г.

C#. Для чего нужны и в каких ситуациях применяются приватные конструкторы?

#c_sharp #ооп #наследование #конструктор #инкапсуляция


Для чего нужны и в каких ситуациях применяются приватные конструкторы?
    


Ответы

Ответ 1



При использовании фабрик классов: public class MyClass { private static Dictionary cache = new Dictionary(); private MyClass() { } public static MyClass GetInstance(object data) { MyClass output; if (!cache.TryGetValue(data, out output)) cache.Add(data, output = new MyClass()); return output; } } За приватным конструктором скрыть какую-то базовую инициализацию: public abstract class BaseClass { private BaseClass() { // здесь какая-то базовая инициализация // этот конструктор должен быть вызван из конструкторов дочерних классов } public class SubClass1 : BaseClass { public SubClass1() : base() { } } public class SubClass2 : BaseClass { public SubClass2() : base() { } } } Дочерние классы должны вызвать конструктор базового класса, где происходит инициализация базовая. В общем и целом, как правило, приватные конструкторы используют для предотвращения создания объекта класса из вне (используется в синглтонах, фабриках и т.п).

Ответ 2



Приватный конструктор применяется, понятно, для случаев, когда вы не хотите, чтобы он был доступен снаружи. Например, у вас может быть клонирующий конструктор, который создаёт объект из значений его полей. Поскольку вы не хотите показывать всему миру поля, то вы прячете этот конструктор, и вызываете его в методе Clone(). class A : ICloneable { int id; string name; static Random random = new Random(); public A(string name) { this.id = random.Next(); this.name = "name #" + this.id; } pulbic object Clone() { return new A(id, name); } private A(int id, string name) { this.id = id; this.name = name; } } Или например, вы хотите, чтобы у вас контролируемое количество объектов. Например, объект — это ось координат, и вам нужно, чтобы их было ровно три: X, Y и Z. Тогда вы прячете конструктор, и выставляете готовые объекты: class Axis { public string Name { get; } public Vector Direction { get; } private Axis(string name, Vector direction) { Name = name; Direction = direction; } static public readonly Axis X = new Axis("X", new Vector(1, 0, 0); static public readonly Axis Y = new Axis("Y", new Vector(0, 1, 0); static public readonly Axis Z = new Axis("Z", new Vector(0, 0, 1); } Ещё пример: у вас есть несколько конструкторов с одинаковой сигнатурой. Как быть? Добавить фиктивный параметр и заставлять пользователя догадаться, какой из них что значит? Лучшее решение — спрятать конструктор, и использовать статические методы: class Point { public double X { get; } public double Y { get; } public double R { get; } public double Phi { get; } private Point(double x, double y, double r, double phi) { X = x; Y = y; R = r; Phi = phi; } public static Point FromCartesian(double x, double y) { double r = Math.Sqrt(x * x + y * y); double phi = Math.Atan2(y, x); return new Point(x, y, r, phi); } public static Point FromPolar(double r, double phi) { double x = r * Math.Cos(phi); double yx = r * Math.Sin(phi); return new Point(x, y, r, phi); } } Или у вас создание объекта асинхронно, потому что вам необходимо совершить асинхронную операцию в нём. Вы снова-таки выносите асинхронную операцию в статическую функцию, а конструктор делаете приватным: class Transmitter { public static async Task Create(IPAddress addr, int port) { var t = new Transmitter(); await t.client.ConnectAsync(addr, port); return t; } private Transmitter() { } // не доступно снаружи private TcpClient client = new TcpClient(); }

Комментариев нет:

Отправить комментарий