매개 변수를 사용하여 기본 매개 변수 없는 생성자를 생성할 때 해당 생성자가 사라지는 이유는 무엇입니까?
C#, C++ 및 Java에서는 파라미터를 사용하는 컨스트럭터를 작성하면 기본 파라미터가 없는 컨스트럭터가 사라집니다.나는 항상 이 사실을 받아 들였지만, 지금은 왜 그런지 궁금해지기 시작했다.
이 동작의 원인은 무엇입니까?「자신의 시공자를 만들었다면, 이 암묵적인 시공자가 서성이고 싶지 않을지도 모른다」라고 하는 「안전 대책/추측」에 지나지 않는가.아니면 사용자가 직접 컨스트럭터를 만든 후 컴파일러가 컴파일러를 추가할 수 없는 기술적 이유가 있습니까?
컴파일러가 컨스트럭터를 추가하지 못할 이유가 없습니다.컴파일러는 원하는 대로 할 수 있습니다.단, 가장 타당한 것은 다음과 같습니다.
- 비정적 클래스의 컨스트럭터를 정의하지 않은 경우 해당 클래스를 인스턴스화할 수 있어야 합니다.이를 허용하기 위해 컴파일러는 파라미터 없는 생성자를 추가해야 하며, 이는 인스턴스화를 허용하는 것 외에는 아무런 효과가 없습니다.즉, 코드에 빈 컨스트럭터를 포함할 필요가 없습니다.
- 자체 생성자(특히 매개 변수가 있는 생성자)를 정의했다면 클래스를 만들 때 실행해야 하는 나만의 논리가 있을 수 있습니다.이 경우 컴파일러가 빈 파라미터가 없는 컨스트럭터를 작성하면 내가 작성한 로직을 누군가가 건너뛸 수 있기 때문에 모든 방법으로 코드가 깨질 수 있습니다.이 경우 기본 빈 생성자를 사용하려면 명시적으로 입력해야 합니다.
따라서 어느 경우든 현재 컴파일러의 동작은 코드의 의도성을 유지하는 데 가장 타당하다는 것을 알 수 있습니다.
언어를 이런 식으로 설계해야 할 기술적인 이유는 전혀 없습니다.
다소 사실적인 4가지 옵션이 있습니다.
- 기본 생성자가 전혀 없습니다.
- 현재의 시나리오
- 기본적으로 항상 기본 생성자를 제공하지만 명시적으로 억제할 수 있습니다.
- 기본 생성자를 억제하지 않고 항상 제공
옵션 1은 어느 정도 매력적입니다.코딩을 하면 할수록 파라미터가 없는 컨스트럭터를 필요로 하지 않습니다.언젠가 디폴트 컨스트럭터를 사용하게 되는 빈도를 세어봐야 할 것 같아요.
옵션 2 난 괜찮아.
옵션 3은 나머지 언어에서는 Java와 C#의 흐름에 역행합니다.Java의 디폴트보다 사생활을 명시적으로 하지 않는 한, 명시적으로 「삭제」하는 것은 없습니다.
옵션 4는 끔찍합니다. 특정 매개변수를 사용하여 강제로 시공할 수 있어야 합니다.어떻게 하면 좋을까?new FileStream()
비열해?
기본적으로 디폴트 컨스트럭터를 제공하는 것이 타당하다는 전제를 받아들인다면 자신의 컨스트럭터를 제공하는 즉시 억제하는 것이 매우 타당하다고 생각합니다.
편집. 사실 첫 번째 답변에서 말한 것은 유효하지만, 이것이 진짜 이유입니다.
처음에는 C가 있었다.C는 객체 지향적이지 않습니다(OO 접근 방식을 취할 수 있지만, 당신에게 도움이 되거나 강요하지는 않습니다).
그리고 C With Classes가 있었는데 나중에 C++로 이름이 바뀌었습니다.C++는 객체 지향적이므로 캡슐화를 장려하고 객체의 불변성을 보장합니다.구축 시, 메서드의 시작 및 종료 시 객체는 유효한 상태에 있습니다.
이를 위해 당연히 클래스에는 유효한 상태에서 시작할 수 있도록 항상 생성자가 있어야 합니다. 생성자가 이를 위해 아무것도 할 필요가 없는 경우 빈 생성자가 이 사실을 문서화합니다.
그러나 C++의 목표는 가능한 한 모든 유효한 C 프로그램도 유효한 C++ 프로그램이라는 점에서 C와 호환되는 것이었다(더 이상 액티브한 목표가 아니며 C++로 분리된 C의 진화는 C++가 더 이상 유지되지 않는다는 것을 의미한다).
이것의 한 가지 효과는 두 가지 기능 간의 중복이었습니다.struct
그리고.class
전자는 C 방식(기본적으로 모든 공개)으로, 후자는 좋은 OO 방식(기본적으로 모든 비공개, 개발자는 자신이 원하는 공개)으로 작업을 수행합니다.
또 하나는 C를 위해서struct
C에 컨스트럭터가 없기 때문에 컨스트럭터를 가질 수 없는 C++에서 유효하게 하려면 C++의 관점에서 이것에 대한 의미가 있어야 합니다.따라서 컨스트럭터가 없는 것은 불변성을 적극적으로 보장하는 OO의 관행에 반하는 것이지만, C++는 이를 빈 바디를 가진 것처럼 동작하는 파라미터가 없는 디폴트 컨스트럭터가 있음을 의미합니다.
모두 Cstructs
유효한 C++가 되었습니다.structs
(즉, C++와 같음)classes
모든 것(멤버 및 상속 - 퍼블릭)을 파라미터가 없는 단일 생성자가 있는 것처럼 외부에서 처리합니다.
어떤 식으로든 컨스트럭터를 삽입한 경우class
또는struct
C 방식이 아닌 C++/OO 방식으로 작업을 수행하므로 기본 컨스트럭터가 필요하지 않습니다.
약자 역할을 했기 때문에 호환성이 없는 경우에도 계속 사용할 수 있었습니다(C에 없는 다른 C++ 기능을 사용).
따라서 Java(다양한 방법으로 C++를 기반으로 함)와 나중에 C#(다른 방법으로 C++와 Java를 기반으로 함)이 등장했을 때 이미 코더가 익숙한 접근 방식을 유지했습니다.
Strustrup은 이에 대해 C++의 설계와 진화에서 언어의 '화색'에 더 초점을 맞추어 C++ 프로그래밍 언어에서 쓰고 있습니다.
=== 오리지널 답안 ===
이 일이 일어나지 않았다고 칩시다.
파라미터가 없는 컨스트럭터는 필요 없습니다.컨스트럭터가 없으면 클래스를 의미 있는 상태로 만들 수 없기 때문입니다.실제로, 이것은, 다음의 경우에 일어날 수 있는 일입니다.struct
(단, 모든 제로 앤 늘을 의미 있게 사용할 수 없는 경우)struct
C#에서는 공개되지 않는 최적화를 사용하는 것이 좋으며, 그렇지 않으면 설계상의 결함이 있습니다.struct
).
내 학급이 불변한 학생들을 보호할 수 있도록 하기 위해, 나는 특별한 것이 필요하다.removeDefaultConstructor
키워드를 지정합니다.적어도 디폴트를 호출하는 호출 코드가 없는지 확인하기 위해 파라미터가 없는 프라이빗 컨스트럭터를 작성해야 합니다.
그래서 언어를 더 복잡하게 만들죠하지 않는 게 좋겠어.
기본적으로 컨스트럭터를 추가하는 것은 디폴트를 삭제하는 것으로 생각하지 말고 컨스트럭터를 전혀 사용하지 않는 파라미터가 없는 컨스트럭터를 추가하는 구문설탕으로 생각하는 것이 좋습니다.
개체 생성을 직접 제어하지 않으면 매개 변수가 없는 기본 생성자가 추가됩니다.컨트롤할 컨스트럭터를 1개 작성하면 컴파일러가 "오프"하여 완전한 컨트롤이 가능하게 됩니다.
이렇게 하지 않으면 매개 변수가 있는 생성자를 통해서만 개체를 구성할 수 있도록 하려면 기본 생성자를 비활성화하는 명시적인 방법이 필요합니다.
컴파일러의 편리한 기능입니다.매개 변수를 사용하여 생성자를 정의하지만 매개 변수 없는 생성자를 정의하지 않으면 매개 변수 없는 생성자를 허용하지 않을 가능성이 훨씬 높아집니다.
빈 생성자를 사용하여 초기화하는 것이 의미가 없는 객체의 경우가 대부분입니다.
그렇지 않으면 제한할 각 클래스에 대해 개인 매개 변수 없는 생성자를 선언해야 합니다.
내 생각에, 기능하기 위해 매개 변수가 필요한 클래스에 매개 변수가 없는 생성자를 허용하는 것은 좋지 않은 스타일입니다.
문제는 정반대로 해야 한다고 생각합니다.다른 생성자를 정의하지 않은 경우 기본 생성자를 선언할 필요가 없습니다.
비정적 클래스의 경우 생성자는 필수입니다.
따라서 컨스트럭터를 정의하지 않은 경우 생성된 디폴트 컨스트럭터는 C# 컴파일러의 편리한 기능일 뿐이며 컨스트럭터가 없으면 클래스는 유효하지 않습니다.따라서 아무 것도 하지 않는 생성자를 암묵적으로 생성하는 것은 문제가 되지 않습니다.주변에 빈 시공자가 있는 것보다 확실히 깨끗해 보입니다.
컨스트럭터를 이미 정의했다면 클래스는 유효합니다.왜 컴파일러는 디폴트 컨스트럭터를 필요로 한다고 가정합니까?만약 원하지 않는다면요?컴파일러에게 기본 생성자를 생성하지 않도록 지시하는 속성을 구현하시겠습니까?그건 좋은 생각이 아닌 것 같아.
기본 생성자는 클래스에 생성자가 없는 경우에만 생성할 수 있습니다.컴파일러는 이를 백업 메커니즘으로만 제공하는 방식으로 작성됩니다.
매개 변수화된 생성자가 있는 경우 기본 생성자를 사용하여 개체를 생성하지 않을 수 있습니다.컴파일러가 기본 컨스트럭터를 제공했다면 인수를 사용하지 않고 오브젝트가 생성되지 않도록 하기 위해 no-arg 컨스트럭터를 작성하여 비공개로 해야 했을 것입니다.
또, 디폴트 컨스트럭터를 무효로 하거나 「프라이버시」하는 것을 잊어버리고, 그 결과 검출하기 어려운 기능 에러가 발생할 가능성이 높아집니다.
기본 방법 또는 매개 변수를 전달하여 개체를 만들려면 no-arg 생성자를 명시적으로 정의해야 합니다.이것은 강하게 체크되고 컴파일러는 다른 방법으로 불만을 표시하기 때문에 여기에 구멍이 나지 않습니다.
전제
이 동작은 클래스에 기본 공개 파라미터가 없는 생성자를 지정하기 위한 의사결정의 자연스러운 확장으로 볼 수 있습니다.지금까지의 질문에 근거해, 이 결정을 전제로 해, 이 케이스에서는 의문을 제기하고 있지 않다고 가정합니다.
기본 생성자를 삭제하는 방법
따라서 기본 공용 매개 변수 없는 생성자를 제거할 수 있는 방법이 있어야 합니다.이 제거는 다음과 같은 방법으로 수행할 수 있습니다.
- 공개되지 않은 매개 변수 없는 생성자 선언
- 매개 변수가 있는 생성자가 선언되면 매개 변수가 없는 생성자를 자동으로 제거합니다.
- 파라미터가 없는 컨스트럭터를 삭제하도록 컴파일러에 지시하는 키워드/아트리뷰트(배제하기 쉬울 정도로 어색함)
최적의 솔루션 선택
이제 우리는 스스로에게 묻습니다.파라미터가 없는 생성자가 없는 경우 대체해야 하는 것은 무엇입니까?또한 어떤 시나리오에서 기본 퍼블릭파라미터 없는 생성자를 삭제해야 합니까?
일이 제대로 돌아가기 시작한다.먼저 매개 변수가 있는 생성자 또는 공개되지 않은 생성자로 대체해야 합니다.다음으로 파라미터가 없는 컨스트럭터를 필요로 하지 않는 시나리오는 다음과 같습니다.
- 클래스를 인스턴스화하지 않거나 생성자의 가시성을 제어하고 싶다.비공개 생성자를 선언한다.
- 구성 시 매개 변수를 강제로 제공하려고 합니다. 매개 변수를 사용하여 생성자를 선언합니다.
결론
여기에서는 C#, C++ 및 Java가 기본 공개 파라미터 없는 컨스트럭터를 삭제할 수 있도록 하는 두 가지 방법이 있습니다.
이건 컴파일러가 처리하는 것 같아요.를 열면.net
에 조립하다.ILDASM
기본 생성자가 코드에 없는 경우에도 표시됩니다.매개 변수화된 생성자를 정의하면 기본 생성자가 표시되지 않습니다.
실제로 클래스(비정적)를 정의하면 컴파일러는 이 기능을 제공합니다.인스턴스만 작성한다고 생각됩니다.또, 특정의 조작을 실시하려면 , 반드시 독자적인 컨스트럭터가 필요합니다.
왜냐하면 사용자가 컨스트럭터를 정의하지 않으면 컴파일러는 자동으로 인수를 사용하지 않는 컨스트럭터를 생성하기 때문입니다.건설업자에게서 더 많은 것을 얻고 싶을 때, 당신은 그것을 오버라이드합니다.이것은 함수의 오버로드가 아닙니다.따라서 현재 컴파일러에서 볼 수 있는 유일한 생성자는 인수를 사용하는 생성자입니다.이 문제에 대처하기 위해 생성자가 값 없이 전달된 경우 기본값을 전달할 수 있습니다.
클래스에는 생성자가 필요합니다.이것은 필수 조건입니다.
- 생성하지 않으면 파라미터가 없는 생성자가 자동으로 지정됩니다.
- 매개 변수가 없는 생성자를 원하지 않는 경우 자체 생성자를 만들어야 합니다.
- 매개 변수 없는 생성자와 매개 변수 기반 생성자를 모두 필요로 하는 경우 수동으로 추가할 수 있습니다.
다른 질문으로 답변하겠습니다.왜 항상 파라미터가 없는 디폴트 컨스트럭터를 원합니까?이것이 바람직하지 않은 경우가 있기 때문에 개발자는 필요에 따라 추가 또는 삭제할 수 있습니다.
언급URL : https://stackoverflow.com/questions/11792207/why-does-the-default-parameterless-constructor-go-away-when-you-create-one-with
'programing' 카테고리의 다른 글
Vue에서 선택한 옵션을 조건부로 설정하는 방법 (0) | 2022.05.30 |
---|---|
main() 메서드는 C에서 어떻게 동작합니까? (0) | 2022.05.30 |
VueJS 컴포넌트에서 윈도 스크롤이벤트를 듣는 방법 (0) | 2022.05.30 |
C의 플래그를 삭제하려면 어떻게 해야 하나요? (0) | 2022.05.30 |
AM/PM과 함께 현재 시간을 12시간 형식으로 표시 (0) | 2022.05.30 |