Зачем нужен приватный конструктор

Обновлено: 28.04.2024

Почему мы должны сделать конструктор приватным в классе? Поскольку нам всегда нужно, чтобы конструктор был общедоступным.

некоторые причины, по которым вам может понадобиться частный конструктор:

  1. конструктор может быть доступен только из статический метод фабрики внутри самого класса. Синглтон также может принадлежать к этой категории.
  2. служебный класс, который содержит только статические методы.

предоставляя частный конструктор, вы предотвращаете создание экземпляров класса в любом месте, кроме этого самого класса. Существует несколько вариантов использования для предоставления такого конструктора.

А. экземпляры класса создаются в static метод. The static метод затем объявляется как public .

Б. свой класс синглтон. Это означает, что в классе существует не более одного экземпляра программа.

C. (применяется только к предстоящему стандарту C++0x) у вас есть несколько конструкторов. Некоторые из них объявлены public , другие private . Для уменьшения размера кода публичные конструкторы "вызывают" частные конструкторы, которые, в свою очередь, выполняют всю работу. Ваш public конструкторы называются делегируя конструкторы:

D. Вы хотите ограничить копирование объектов (например, из-за использования общего ресурс):

е. ваш класс служебный класс. Это означает, что он содержит только static членов. В этом случае экземпляр объекта должен быть создан в программе.

оставить "заднюю дверь", которая позволяет другому классу/функции друга построить объект способом, запрещенным для пользователя. Примером, который приходит на ум, будет контейнер, создающий итератор (C++):

все застряли на синглтоне, вау.

  • остановите людей от создания вашего класса в стеке; сделайте частные конструкторы и только возвращайте указатели с помощью Заводского метода.
  • предотвращение создания копий класса (конструктор частной копии)

Это может быть очень полезно для конструктора, который содержит общий код; закрытые конструкторы другие конструкторы, с помощью этого(. );' нотация. Делая общий код инициализации в частном (или защищенном) конструкторе, вы также ясно даете понять, что он вызывается только во время построения, что не так, если бы это был просто метод:

есть несколько случаев, когда вы не хотите использовать открытый конструктор; например, если вы хотите одноэлементный класс.

Если вы пишете сборку, используемую третьими сторонами, может быть несколько внутренних классов, которые вы хотите создать только своей сборкой, а не создавать экземпляры пользователями вашей сборки.

Это гарантирует, что вы (класс с частным конструктором) контролируете, как вызывается contructor.

пример: статический заводской метод в классе может возвращать объекты, поскольку заводской метод выбирает их для выделения (например, одноэлементная фабрика).

мы также можем иметь собственный конструктор, для создания объекта определенным классом только(по соображениям безопасности).

один из способов сделать это-иметь класс друга.

Примечание: Примечание: только ClientClass (так как он является другом SecureClass) можно вызвать конструктор SecureClass.

Если это личное, то вы не можете назвать его ==> вы не можете создать экземпляр класса. Полезно в некоторых случаях, как синглтон.

Я видел вопрос от вас по той же проблеме.

просто, если вы не хотите позволять другим создавать экземпляры, то держите constuctor в ограниченной области. Практическое применение (пример) - это одноэлементный шаблон.

вы не стоит сделать конструктор приватным. Период. Сделайте его защищенным, чтобы вы могли расширить класс, если вам нужно.

Edit: я стою на этом, независимо от того, сколько downvotes вы бросаете на это. Вы лишаете код возможности дальнейшего развития. Если другие пользователи или программисты действительно намерены расширить класс, они просто изменят конструктор на protected in source или bytecode. У вас будет не достиг ничего, кроме того, чтобы сделать их жизнь немного сложнее. Включите предупреждение в комментарии вашего конструктора и оставьте его на этом.

если это класс утилиты, то более простым, правильным и элегантным решением является пометка всего класса "static final" для предотвращения расширения. Не стоит просто отмечать конструктор private; действительно определенный пользователь всегда может использовать отражение для получения конструктора.

действующий использует:

  • одно хорошее использование protected конструктор должен принудительно использовать static заводские методы, которые позволяют ограничение создания экземпляра или пула и повторного использования дорогие ресурсы (подключения к БД, native resources).
  • Singletons (обычно не хорошая практика, но иногда необходимо)

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

еще раз, если вы хотите ограничить создание объекта до 10, используйте следующее

у вас может быть несколько конструкторов. C++ предоставляет конструктор по умолчанию и конструктор копирования по умолчанию, если он не указан явно. Предположим, у вас есть класс, который можно построить только с помощью некоторого параметризованного конструктора. Возможно, он инициализировал переменные. Если пользователь использует этот класс без конструктора, они могут вызвать проблемы. Хорошее общее правило: если реализация по умолчанию недопустима, сделайте конструктор default и copy закрытым и не обеспечить реализацию:

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

вот некоторые из частных конструктора :

  1. Синглтон Шаблон Проектирования
  2. чтобы ограничить количество создания экземпляра
  3. чтобы дать значимое имя для создания объекта с помощью статического Заводского метода
  4. Шаблон Проектирования Builder и, таким образом, для создание неизменяемых классов

Если вы не хотите, чтобы пользователи создавали экземпляры этого класса или создавали класс, наследующий этот класс, например java.lang.math , вся функция в этом пакете - static , все функции могут быть вызваны без создания экземпляра math , поэтому конструктор объявляется как статический.

цитирую Эффективная Java, вы можете иметь класс с частным конструктором, чтобы иметь класс утилиты, который определяет константы (как статические конечные поля).

( EDIT: согласно комментарию это то, что может быть применимо только с Java, я не знаю, применима ли эта конструкция/необходима в других языках OO (скажем, c++))

пример, как показано ниже:

EDIT_1: Again, below explanation is applicable in Java : (and referring from the book, Effective Java)

An instantiation of utility class like the one below ,though not harmful, doesn't serve any purpose since they are not designed to be instantiated.

For example, say there is no private Constructor for class Constants. A code chunk like below is valid but doesn't better convey intention of the user of Constants class

в отличие от кода

также я думаю, что частный конструктор передает намерение дизайнера константы класс лучше.

Java предоставляет открытый конструктор без параметров по умолчанию, если нет конструктора и если ваше намерение состоит в том, чтобы предотвратить создание экземпляров, то отдельный конструктор необходимый.

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

служебные классы могут быть частными застройщиками. Пользователи классов не должны иметь возможность создавать экземпляры этих классов:

вы можете запретить свободный экземпляр класса. См. шаблон проектирования singleton в качестве примера. Чтобы гарантировать уникальность, вы не можете позволить никому создать его экземпляр: -)

одно из важных применений - в Одноэлементном классе

также подходит, если ваш класс имеет только статические методы. я.е никто не должен инстанцировать класс

это действительно одна очевидная причина: вы хотите построить объект, но это не практично делать (с точки зрения интерфейса) в конструкторе.

на Factory пример вполне очевиден, позвольте мне продемонстрировать Named Constructor идиома.

скажем у меня есть класс Complex который может представлять собой комплексное число.

вопрос в том, ожидает ли конструктор реальную и мнимую части, или он ожидает норму и угол (полярные координаты) ?

Я могу изменить интерфейс, чтобы сделать его проще:

это называется Named Constructor идиома: класс может быть построен только с нуля, явно указав, какой конструктор мы хотим использовать.

это особый случай многих методов строительства. Шаблоны проектирования предоставляют большое количество способов построения объекта: Builder , Factory , Abstract Factory , . и частный конструктор гарантирует, что пользователь правильно ограничен.

В дополнение к более известным использует.

для реализации Метод Объекта шаблон, который я бы суммировал как:

"частный конструктор, публичный статический метод"
"Объект для реализации, функция для интерфейса"

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

. замена его вызовом функции (namespaced):

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

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

этот шаблон объекта метода приведен в Smalltalk Лучшие Образцы Практики, Кент Бек, страницы 34-37, где это последний шаг рефакторинга, заканчивающийся:

  1. заменить оригинальный метод, который создает экземпляр нового класса, построен с параметрами и приемником исходного метода и вызывает "compute".

это существенно отличается от других примеров здесь: класс инстанцируемая (в отличие от служебного класса), но случаи частные (в отличие от фабричных методов, включая одиночек и т. д.), и могут жить на стеке, так как они никогда не убегают.

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

иногда полезно, если вы хотите контролировать, как и когда (и сколько) экземпляров объекта создаются.

среди прочего, используется в шаблонах:

при использовании частных конструкторов также можно повысить читаемость / ремонтопригодность перед лицом доменного дизайна. От "Microsoft .Нетто - Architecing приложений для предприятия, 2-е издание":

цитирую: "здесь есть две проблемы. Во-первых, глядя на код, трудно догадаться, что происходит на. Создается экземпляр OrderRequest, но почему и с помощью каких данных? Что 1234? Этот приводит ко второй проблеме: вы нарушаете вездесущий язык ограниченного контекста. Этот язык, вероятно, говорит что-то вроде этого: клиент может оформить запрос на заказ и может укажите идентификатор покупки. Если это так, вот лучший способ получить новый экземпляр OrderRequest:"

Я не выступаю за это для каждого отдельного класса, но для вышеупомянутого сценария DDD я думаю, что имеет смысл предотвратить прямое создание нового объекта.

Можно ли создать объект, если конструктор имеет модификатор private ? Если да, то зачем собственно конструктору нужен модификатор доступа?

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

Приватный конструктор запрещает создание экземпляра класса вне методов самого класса, например, что гарантировать существование только одного объекта определённого класса, предположим какого-то ресурса, например БД.

можно. чтобы создавать только из статических методов данного класса. сделать что-то типа фабрики.

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

Ещё такие классы с приватными конструкторами используют для создания утилитарных классов, в которых есть только static методы.

Модификатор доступа private определяет доступ в рамках данного класса, где вы можете создавать объекты. Т.е. вы не сможете создать объект этого класса за его пределами, так например с помощью new из другого класса или блока.

Конечно если вы не используете рефлексию, которая может изменить положение вещей.

Зачем это нужно, ну скажем вы хотите контролировать создание объектов внутри класса.

Это может делаться в том случае если для работы с классом не нужны его объекты: яркий пример утильные классы в которых все методы статические для работы с которыми объекты класса не нужны. К примеру класс java.util.Collections, который определяет вспомогательные методы для работы с коллекциями. Покопайтесь в нём и Вам всё станет понятно. Как говорится "Больше тысячи слов". Повторюсь: модификатор private конструктору нужен, для того чтобы снаружи класса нельзя было создавать объекты через этот конструктор и им можно было пользоваться только внутри самого класса, а применений масса.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками java ооп конструктор или задайте свой вопрос.

Похожие

Для подписки на ленту скопируйте и вставьте эту ссылку в вашу программу для чтения RSS.

Site design / logo © 2022 Stack Exchange Inc; user contributions licensed under cc by-sa. rev 2022.6.21.42407

Нажимая «Принять все файлы cookie», вы соглашаетесь, что Stack Exchange может хранить файлы cookie на вашем устройстве и раскрывать информацию в соответствии с нашей Политикой в отношении файлов cookie.

If a class has a private constructor then it can't be instantiated. So, if I don't want my class to be instantiated and still use it, then I can make it static.

What is the use of a private constructor?

Also, it's used in the singleton class, but except for that, is there any other use?

(Note: The reason I am excluding the singleton case above is that I don't understand why we need a singleton at all when there is a static class available. You may not answer this for my confusion in the question. )

10 Answers 10

Factory

Private constructors can be useful when using a factory pattern (in other words, a static function that's used to obtain an instance of the class rather than explicit instantiation).

Pseudo-Sealed with Nested Children

Any nested classes that inherit from the outer class can access the private constructor.

For instance, you can use this to create an abstract class that you can inherit from, but no one else (an internal constructor would also work here to restrict inheritance to a single assembly, but the private constructor forces all implementations to be nested classes.)

Base Constructor

They can also be used to create "base" constructors that are called from different, more accessible constructors.

I like the assignment inside the cache add statement, I've used that syntax for lazily loaded properties with the null coalescing operator it didn't occur to me before that it can equally be used in regular methods before now.

As Stefan, Adam and other have pointed out, private constructors are useful in cases where it is undesirable for a class to be created by code outside of the class. Singletons, factories, static method objects are examples of where being able to restrict constructon of a type is useful to enforce a particular pattern.

To respond to the second part of your question about why singletons are needed if static classes exist: singletons and static classes are not equivalent.

For example, a singleton class can implement an interface, a static class cannot. A singleton object may be passed to methods as a parameter - this is not so easy to do with static classes without resorting to wrapper objects or reflection. There are also cases where you may want to create an inheritance hierarchy in which one (or more) of the leaf classes are singleton - this is not possible with static classes either. As another example, you may have several different singletons and you may want to instantiate one of them at runtime based on environmental or configurational parameters - this is also not possible with static classes.

It is important to understand the language features and choose the right one for the job - they're there for a reason.

Определение приватного конструктора - это паттерн, используемый в объектно-ориентированных языках программирования, который предотвращает создание экземпляра класса, вызовом из вне конструкции new ClassName() . Эта паттерн, который наделяет класс возсожностью создать объект только изнутри самого себя (ниже покажу детальнее, что это значит).

Впервые увидев этот паттерн на практике, я был немного растерян. Не сразу было понятно, где такая функция будет полезна в реальном мире, и какой смысл в создании private конструктора. В сознании возникал логичный вопрос: как вы собираетесь использовать класс, если он не может быть создан снаружи? Зачем вообще пытаться определить конструктор, если он не может быть вызван?

Но, оказывается, есть несколько случаев использования, когда приватный конструкторы приходятся очень кстати. В этой статье я расскажу о нескольких случаях, в которых он несёт несослужимую службу. Примеры приведены на PHP, но их можно перенести на любой язык объектно-ориентированный язык программирования, который поддерживает эту функцию.

Основы

Когда вы попытаетесь создать экземпляр класса с приватным конструктором, вы получите фатальную ошибку, аналогично тому, если бы вы пытались вызвать любой другой приватный метод объекта.

Однако, при таком подходе, путём наследования, можно переопределить родительский конструктор, и открыть его для клиентского кода. Это означает, что класс может по-прежнему создаваться людьми, использующими его снаружи, если он только не объявлен как final , что подразумевает отсутствие возможности наследования.

Если унаследованный класс определяет свой собственный конструктор, оригинальный, приватный, не будет вызван.

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

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

Синглтоны (Singletons)

Синглтон (объект одиночка) - это объект, который может быть создан только один раз за время выполнения приложения. В случаях попытки создания нового объекта синглтона, будет возвращать ранее (первый) созданный объект данного класса. Обычно это реализуется в контейнере внедрения зависимостей или объектах запроса/ответа веб-фреймворка.

С помощью приватного конструктора мы можем заставить программистов взаимодействовать с ним только через статический метод, в котором реализуем код создания синглтона на PHP. В результате чего, будет существовать только одна возможность создания экземпляра нашего класса - через статический метод. А в этом методе уже реализуем условие по которому будет создавать именно синглтон, вместо того, чтобы поручать пользователю делать это самостоятельно.

Обратите внимание, что независимо от того, сколько раз мы вызываем Singleton::getInstance() , возвращается один и тот же экземпляр объекта с одним и тем же идентификатором.

Класс, содержащий только статические методы

Иногда нам требуется создавать классы хелперы, которые не решают какую-то конкретную задачу, а просто содержат статические методы, лишь помогающие решить какую-то незначительную часть задачи. Каждый метод таких классов выступает в роли утилиты, поэтому, для подобных классов нет оснований для создания его экземпляра.

Хотя этого и можно достичь, объявив класс как абстрактный (чтобы его объект нельзя было создать самостоятельно, это смогут сделать только унаследовавшие его классы), это также можно реализовать с помощью определения пустого приватного конструктора.

Предопределённые значения

Иногда вам может потребоваться создать экземпляр класса, над которым вы хотите получить больший контроль при его создании, и, какие параметры он может принимать, например, иметь заранее определённый список значений. Подобным подходом мы воспользовались в начале статьи, когда запретили создание пользователя напрямую через конструктор, инкапсулировав логику их создания в статические методы: user() , и admin() .

Другая возможность - это нормализация/модификация входных параметров, и создание на основании них нужных экземпляр класса.

Enum-значения в PHP

Поскольку PHP не имеет собственного типа enum , они обычно обрабатываются путем добавления констант в класс. Поскольку к константам класса можно обращаться статически, экземпляр этих классов не требуется создавать.

С полностью пустым приватным конструктором мы можем предотвратить создание экземпляров подобных классов.

Резюме

Из этой статьи вы должны были увидели, что есть множество полезных применений приватного конструктора в PHP, при которых они являются идеальным решением. Несмотря на то, что они часто упускаются из виду в пользу других функций, которые может иметь язык программирования, таких как абстрактные классы/методы или перегрузка методов (не для PHP), они так же имеют место быть.

Надеюсь, эта статья полностью и доступно помогла вам понять, зачем нужен приватный конструктор в PHP, и как его использовать. А так же, благодаря этой статье вы дополнительно узнали, как в PHP создаётся синглтон нативными средствами.

На собеседованиях иногда спрашивают зачем нужен (может применяться) приватный конструктор в С++. На самом деле, зачем, ведь тогда мы не сможем его вызвать, а значит — создать объект?

Конструктор помещается в секцию private в случаях, если нужно ограничить пользователя в возможностях создания объектов. Часто так поступают с конструктором копирования, если хотят запретить эту операцию (обычно вместе с этим в приватную секцию помещают оператор присваивания):

Если нужно запретить операцию копирования, то имеет смысл объявить функции с ключевым словом delete или объявить, но не реализовывать, т.к. в противном случае их смогут использовать функции-члены класса, а также функции дружественных классов.
Чтобы запретить копирование достаточно создать дочерний класс от boost::noncopyable , у которого эти операции приватные.
Примером такого класса из стандартной библиотеки является fstream , предоставляющий возможность работы с файловыми потоками, кроме того, это могут быть различные классы работы с БД, мьютексами, очень большими объектами, копирование которых не эффективно.

Кроме того, закрытые конструкторы применяются если для порождения объектов пользователь должен использовать специальную функцию. Эта функция может выполнять ряд дополнительных действий, не допустимых для конструктора. Такой подход применяется в ряде шаблонов проектирования:

  • Singleton [пример использования шаблона Singleton для работы с базой данных], управляет созданием объектов, следит за тем, чтобы существовал только один экземпляр класса, который либо создается, либо возвращается уже готовый. Конструктор должен в любом случае создать объект, поэтому созданием занимается отдельная функция;
  • шаблон «Фабричный метод». Есть различные реализации паттерна, но в любом случае порождением объектов занимается отдельная функция, которая может принимать идентификатор класса, объект которого нужно создать:
  • Прототип [пример использования Prototype для реализации меню графического редактора]. Функция, используемая вместо конструктора создает клон существующего объекта и является виртуальной. Конструктор по очевидным причинам не может быть виртуальным.

Читайте также: