Programing

클래스에서 생성자를 비공개로 사용하는 것은 무엇입니까?

crosscheck 2020. 7. 7. 07:46
반응형

클래스에서 생성자를 비공개로 사용하는 것은 무엇입니까?


클래스에서 생성자를 비공개로 만들어야하는 이유는 무엇입니까? 우리는 항상 생성자가 공개되어야합니다.


개인 생성자가 필요한 몇 가지 이유는 다음과 같습니다.

  1. 생성자는 클래스 자체의 정적 팩토리 메소드 에서만 액세스 할 수 있습니다 . 싱글 톤도이 카테고리에 속할 수 있습니다.
  2. 정적 메소드 만 포함 하는 유틸리티 클래스

개인 생성자를 제공하면이 클래스 이외의 다른 위치에서 클래스 인스턴스가 작성되지 않습니다. 이러한 생성자를 제공하기위한 몇 가지 사용 사례가 있습니다.

A. 클래스 인스턴스는 static메소드 에서 작성됩니다 . static그런 다음 메소드는로 선언됩니다 public.

class MyClass()
{
private:
  MyClass() { }

public:
  static MyClass * CreateInstance() { return new MyClass(); }
};

B. 수업은 싱글 톤 입니다. 이것은 프로그램에 클래스의 인스턴스가 두 개 이상 존재하지 않음을 의미합니다.

class MyClass()
{
private:
  MyClass() { }

public:
  MyClass & Instance()
  {
    static MyClass * aGlobalInst = new MyClass();
    return *aGlobalInst;
  }
};

C. (다가오는 C ++ 0x 표준에만 적용됨) 여러 생성자가 있습니다. 그들 중 일부는 선언 public되고 다른 것들은 선언 됩니다 private. 코드 크기를 줄이기 위해 공개 생성자는 모든 작업을 수행하는 개인 생성자를 '호출'합니다. 귀하의 public생성자 따라서이라고 위임 생성자를 :

class MyClass
{
public:
  MyClass() : MyClass(2010, 1, 1) { }

private:
  MyClass(int theYear, int theMonth, int theDay) { /* do real work */ }
};

D. 개체 복사를 제한하려고합니다 (예 : 공유 리소스 사용으로 인해).

class MyClass
{
  SharedResource * myResource;

private:
  MyClass(const MyClass & theOriginal) { }
};

E. 수업은 유틸리티 수업 입니다. 즉, static회원 만 포함한다는 의미 입니다. 이 경우 프로그램에서 개체 인스턴스를 만들면 안됩니다.


다른 친구 클래스 / 함수가 사용자에게 금지 된 방식으로 객체를 구성 할 수있게하는 "후문"을 떠나는 것. 염두에 두는 예는 반복자를 구성하는 컨테이너 (C ++)입니다.

Iterator Container::begin() { return Iterator(this->beginPtr_); }
// Iterator(pointer_type p) constructor is private,
//     and Container is a friend of Iterator.

모두 싱글 톤에 갇혀있어

다른 것들:

  • 사람들이 스택에서 수업을 만들지 못하게합니다. 개인 생성자를 만들고 팩토리 메소드를 통해 포인터를 넘겨줍니다.
  • 클래스 사본 작성 금지 (개인 사본 생성자)

이것은 공통 코드를 포함하는 생성자에게 매우 유용 할 수 있습니다. 개인 생성자는 'this (...);'를 사용하여 다른 생성자가 호출 할 수 있습니다. 표기법. 개인 (또는 보호 된) 생성자에서 공통 초기화 코드를 만들면 코드가 생성 중에 만 호출된다는 것을 분명히 알 수 있습니다.

public class Point {
   public Point() {
     this(0,0); // call common constructor
   }
   private Point(int x,int y) {
     m_x = x; m_y = y;
   }
};

공개 생성자를 사용하고 싶지 않은 경우가 있습니다. 예를 들어 싱글 톤 클래스를 원한다면

타사에서 사용하는 어셈블리를 작성하는 경우 어셈블리에서만 생성하고 어셈블리 사용자가 인스턴스화하지 않는 여러 내부 클래스가있을 수 있습니다.


이를 통해 사용자 (개인 생성자가있는 클래스)가 생성자 호출 방식을 제어 할 수 있습니다.

예제 : 팩토리 메소드가 객체를 할당하기로 선택한 경우 (예 : 싱글 톤 팩토리와 같이) 클래스의 정적 팩토리 메소드가 객체를 반환 할 수 있습니다.


또한 특정 클래스만으로 객체를 생성하기 위해 개인 생성자를 가질 수도 있습니다 (보안상의 이유로).

그것을하는 한 가지 방법은 친구 수업을하는 것입니다.

C ++ 예 :

class ClientClass;
class SecureClass 
{
  private:
    SecureClass();   // Constructor is private.
    friend class ClientClass;  // All methods in 
                               //ClientClass have access to private
                               // &   protected methods of SecureClass.
};

class ClientClass
{
public:
    ClientClass();
    SecureClass* CreateSecureClass()
     { 
           return (new SecureClass());  // we can access 
                                        // constructor of 
                                        // SecureClass as 
                                        // ClientClass is friend 
                                        // of SecureClass.
     }
};

참고 : ¬¸ × Ì : SecureClass의 친구이므로 ClientClass 만 SecureClass의 생성자를 호출 할 수 있습니다.


private 생성자의 사용법은 다음과 같습니다.

  1. 싱글 톤 디자인 패턴
  2. 인스턴스 생성 수를 제한하려면
  3. 정적 팩토리 메소드를 사용하여 오브젝트 작성에 의미있는 이름을 부여하려면
  4. 정적 유틸리티 클래스 또는 상수 클래스
  5. 서브 클래 싱을 방지하려면
  6. 빌더 디자인 패턴변경 불가능한 클래스 작성

비공개 인 경우 ==>라고 호출 할 수 없으며 클래스를 인스턴스화 할 수 없습니다. 싱글 톤과 같은 경우에 유용합니다.

여기에 토론과 더 많은 예제가 있습니다 .


같은 문제를 해결하는 질문이 있습니다.

다른 사람이 인스턴스를 생성하지 못하게하려면 컨스트럭터를 제한된 범위 내로 유지하십시오. 실제 응용 (예)은 싱글 톤 패턴입니다.


당신은 생성자는 비공개. 기간. 필요한 경우 수업을 확장 할 수 있도록 보호하십시오.

편집 : 나는 당신이 이것에 던지는 공무원 수에 관계없이 그것을 기다리고 있습니다. 코드에서 향후 개발 가능성을 차단하고 있습니다. 다른 사용자 나 프로그래머가 실제로 클래스를 확장하기로 결정한 경우 생성자를 소스 또는 바이트 코드로 보호하도록 변경하면됩니다. 당신은 그들의 삶을 조금 더 어렵게 만드는 것 외에는 아무것도 성취하지 못할 것입니다. 생성자의 주석에 경고를 포함하고 그 상태로 두십시오.

유틸리티 클래스 인 경우 더 간단하고 정확하며 우아한 솔루션은 전체 클래스를 "정적 최종"으로 표시하여 확장을 방지하는 것입니다. 생성자를 비공개로 표시하는 것은 좋지 않습니다. 실제로 결정된 사용자는 항상 반영을 사용하여 생성자를 얻을 수 있습니다.

유효한 용도 :

  • protected생성자를 잘 사용하는 한 가지 방법은 정적 팩토리 메소드를 강제로 사용하여 인스턴스화 또는 풀을 제한하고 고가의 리소스 (DB 연결, 기본 리소스)를 재사용 할 수 있습니다.
  • 싱글 톤 (보통 좋은 습관은 아니지만 때로는 필요함)

생성자는 싱글 톤을 구현하거나 클래스의 객체 수를 제한해야 할 때와 같은 목적으로 비공개입니다. 예를 들어 싱글 톤 구현에서는 생성자를 비공개로 만들어야합니다

#include<iostream>
using namespace std;
class singletonClass
{


    static int i;
    static singletonClass* instance;
public:


    static singletonClass* createInstance()
    {


        if(i==0)
        {

            instance =new singletonClass;
            i=1;

        }

        return instance;

    }
    void test()
    {

        cout<<"successfully created instance";
    }
};

int singletonClass::i=0;
singletonClass* singletonClass::instance=NULL;
int main()
{


    singletonClass *temp=singletonClass::createInstance();//////return instance!!!
    temp->test();
}

다시 객체 생성을 10까지 제한하려면 다음을 사용하십시오.

#include<iostream>
using namespace std;
class singletonClass
{


    static int i;
    static singletonClass* instance;
public:


    static singletonClass* createInstance()
    {


        if(i<10)
        {

            instance =new singletonClass;
            i++;
            cout<<"created";

        }

        return instance;

    }
};

int singletonClass::i=0;
singletonClass* singletonClass::instance=NULL;
int main()
{


    singletonClass *temp=singletonClass::createInstance();//return an instance
    singletonClass *temp1=singletonClass::createInstance();///return another instance

}

감사


생성자를 둘 이상 가질 수 있습니다. C ++는 기본 생성자와 기본 복사 생성자를 명시 적으로 제공하지 않으면 제공합니다. 매개 변수화 된 생성자를 사용해서 만 생성 할 수있는 클래스가 있다고 가정하십시오. 변수를 초기화했을 수도 있습니다. 그런 다음 사용자가 해당 생성자없이이 클래스를 사용하면 문제가 발생하지 않습니다. 좋은 일반 규칙 : 기본 구현이 유효하지 않은 경우 기본 및 복사 생성자를 모두 비공개로 설정하고 구현을 제공하지 마십시오.

class C
{
public:
    C(int x);

private:
    C();
    C(const C &);
};

컴파일러를 사용하여 사용자가 유효하지 않은 기본 생성자와 함께 오브젝트를 사용하지 못하게하십시오.


when you do not want users to create instances of this class or create class that inherits this class, like the java.lang.math, all the function in this package is static, all the functions can be called without creating an instance of math, so the constructor is announce as static.


Quoting from Effective Java, you can have a class with private constructor to have a utility class that defines constants (as static final fields).

(EDIT: As per the comment this is something which might be applicable only with Java, I'm unaware if this construct is applicable/needed in other OO languages (say C++))

An example as below:

public class Constants {
    private Contants():

    public static final int ADDRESS_UNIT = 32;
    ...
}

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

unit = (this.length)/new Constants().ADDRESS_UNIT;

in contrast with code like

unit = (this.length)/Constants.ADDRESS_UNIT;

Also I think a private constructor conveys the intention of the designer of the Constants (say) class better.

Java provides a default parameterless public constructor if no constructor is provided, and if your intention is to prevent instantiation then a private constructor is needed.

One cannot mark a top level class static and even a final class can be instantiated.


Utility classes could have private constructors. Users of the classes should not be able to instantiate these classes:

public final class UtilityClass {
    private UtilityClass() {}

    public static utilityMethod1() {
        ...
    }
}

You may want to prevent a class to be instantiated freely. See the singleton design pattern as an example. In order to guarantee the uniqueness, you can't let anyone create an instance of it :-)


One of the important use is in SingleTon class

class Person
{
   private Person()
   {
      //Its private, Hense cannot be Instantiated
   }

   public static Person GetInstance()
   {
       //return new instance of Person
       // In here I will be able to access private constructor
   }
};

Its also suitable, If your class has only static methods. i.e nobody needs to instantiate your class


It's really one obvious reason: you want to build an object, but it's not practical to do it (in term of interface) within the constructor.

The Factory example is quite obvious, let me demonstrate the Named Constructor idiom.

Say I have a class Complex which can represent a complex number.

class Complex { public: Complex(double,double); .... };

The question is: does the constructor expects the real and imaginary parts, or does it expects the norm and angle (polar coordinates) ?

I can change the interface to make it easier:

class Complex
{
public:
  static Complex Regular(double, double = 0.0f);
  static Complex Polar(double, double = 0.0f);
private:
  Complex(double, double);
}; // class Complex

This is called the Named Constructor idiom: the class can only be built from scratch by explicitly stating which constructor we wish to use.

It's a special case of many construction methods. The Design Patterns provide a good number of ways to build object: Builder, Factory, Abstract Factory, ... and a private constructor will ensure that the user is properly constrained.


In addition to the better-known uses…

To implement the Method Object pattern, which I’d summarize as:

“Private constructor, public static method”
“Object for implementation, function for interface”

If you want to implement a function using an object, and the object is not useful outside of doing a one-off computation (by a method call), then you have a Throwaway Object. You can encapsulate the object creation and method call in a static method, preventing this common anti-pattern:

z = new A(x,y).call();

…replacing it with a (namespaced) function call:

z = A.f(x,y);

The caller never needs to know or care that you’re using an object internally, yielding a cleaner interface, and preventing garbage from the object hanging around or incorrect use of the object.

For example, if you want to break up a computation across methods foo, bar, and zork, for example to share state without having to pass many values in and out of functions, you could implement it as follows:

class A {
  public static Z f(x, y) {
    A a = new A(x, y);
    a.foo();
    a.bar();
    return a.zork();
  }

  private A(X x, Y y) { /* ... */ };
}

This Method Object pattern is given in Smalltalk Best Practice Patterns, Kent Beck, pages 34–37, where it is the last step of a refactoring pattern, ending:

  1. Replace the original method with one that creates an instance of the new class, constructed with the parameters and receiver of the original method, and invokes “compute”.

This differs significantly from the other examples here: the class is instantiable (unlike a utility class), but the instances are private (unlike factory methods, including singletons etc.), and can live on the stack, since they never escape.

This pattern is very useful in bottoms-up OOP, where objects are used to simplify low-level implementation, but are not necessarily exposed externally, and contrasts with the top-down OOP that is often presented and begins with high-level interfaces.


Sometimes is useful if you want to control how and when (and how many) instances of an object are created.

Among others, used in patterns:

Singleton pattern
Builder pattern

On use of private constructors could also be to increase readability/maintainability in the face of domain-driven design. From "Microsoft .NET - Architecing Applications for the Enterprise, 2nd Edition":

var request = new OrderRequest(1234);

Quote, "There are two problems here. First, when looking at the code, one can hardly guess what’s going on. An instance of OrderRequest is being created, but why and using which data? What’s 1234? This leads to the second problem: you are violating the ubiquitous language of the bounded context. The language probably says something like this: a customer can issue an order request and is allowed to specify a purchase ID. If that’s the case, here’s a better way to get a new OrderRequest instance:"

var request = OrderRequest.CreateForCustomer(1234);

where

private OrderRequest() { ... }

public OrderRequest CreateForCustomer (int customerId)
{
    var request = new OrderRequest();
    ...
    return request;
}

I'm not advocating this for every single class, but for the above DDD scenario I think it makes perfect sense to prevent a direct creation of a new object.

참고URL : https://stackoverflow.com/questions/2062560/what-is-the-use-of-making-constructor-private-in-a-class

반응형