[java] 매개 변수가없는 생성자를 만들 때 기본 매개 변수없는 생성자가 사라지는 이유

C #, C ++ 및 Java에서 매개 변수를 사용하는 생성자를 만들면 기본 매개 변수가없는 생성자가 사라집니다. 나는 항상이 사실을 받아 들였지만 이제는 왜 그런지 궁금해하기 시작했습니다.

이 행동의 이유는 무엇입니까? “자신의 생성자를 만든 경우이 암시 적 생성자를 원하지 않을 “이라고 말하는 것이 “안전 측정 / 추측” 일 뿐입니 까? 또는 생성자를 직접 만든 후에는 컴파일러에서 컴파일러를 추가 할 수없는 기술적 이유가 있습니까?



답변

직접 추가 한 경우 컴파일러에서 생성자를 추가 할 수있는 이유는 없습니다. 컴파일러는 원하는대로 수행 할 수 있습니다! 그러나 가장 의미가있는 것을 살펴 봐야합니다.

  • 비 정적 클래스에 대한 생성자를 정의 하지 않은 경우 해당 클래스를 인스턴스화 할 수 있기를 원할 것입니다. 이를 허용하기 위해 컴파일러 매개 변수가없는 생성자를 추가 해야합니다 . 즉, 코드를 작성하기 위해 빈 생성자를 내 코드에 포함시킬 필요가 없습니다.
  • 내 자신의 생성자, 특히 매개 변수가있는 생성자를 정의했다면 클래스를 만들 때 실행 해야하는 내 자신의 논리가있을 가능성이 큽니다. 컴파일러 가이 경우 빈 매개 변수가없는 생성자를 만들면 누군가 내가 작성한 논리 를 건너 뛸 수 있으므로 여러 가지 방법으로 코드가 손상 될 수 있습니다. 이 경우 기본 빈 생성자를 원하면 명시 적으로 말해야합니다.

따라서 각 경우에 현재 컴파일러의 동작 이 코드의 의도 를 보존하는 데 가장 적합하다는 것을 알 수 있습니다 .


답변

언어 이런 식으로 설계되어야 하는 기술적 이유는 없습니다 .

내가 볼 수있는 다소 현실적인 옵션이 있습니다.

  1. 기본 생성자가 전혀 없습니다
  2. 현재 시나리오
  3. 기본적으로 항상 기본 생성자를 제공하지만 명시 적으로 억제되도록 허용
  4. 억제 하지 않고 항상 기본 생성자 제공

옵션 1은 더 I 코드가 덜 자주는 점에서 다소 매력적이다 정말 매개 변수없는 생성자를 원한다. 언젠가 나는 기본 생성자를 사용하여 실제로 얼마나 자주 끝나는 지 계산해야합니다 …

옵션 2 괜찮습니다.

옵션 3은 나머지 언어에 대해 Java와 C #의 흐름에 반합니다. Java에서 기본적으로 사적인 것들을 명시 적으로 만드는 것을 제외하고는 명시 적으로 “제거”하는 것은 없습니다.

옵션 4 끔찍 – 당신은 절대적으로 특정 매개 변수와 건설을 강제 할 수 있어야합니다. 무엇을 new FileStream()의미할까요?

그러니까 기본적으로, 경우에 당신은 기본 생성자를 제공하는 것이 전혀 의미가 있다는 전제를 받아, 나는 그것이 바로 당신이 당신의 자신의 생성자를 제공하기로 억제하는 많은 이해 믿습니다.


답변

편집하다. 사실, 첫 번째 답변에서 내가 말하는 것은 유효하지만 이것이 진정한 이유입니다. :

처음에는 C가있었습니다. C는 객체 지향적이지 않습니다 (OO 접근 방식을 취할 수는 있지만 도움이되지 않습니다).

그런 다음 C With Classes가 있었고 나중에 C ++로 이름이 바뀌 었습니다. C ++는 객체 지향적이므로 캡슐화를 장려하고 구성시 및 메소드 시작 및 종료시 객체가 유효한 상태에있게합니다.

이것과 관련된 자연스러운 일은 클래스가 항상 유효한 상태에서 시작되도록 생성자가 있어야한다는 것입니다. 생성자가 이것을 보장하기 위해 아무것도 할 필요가 없다면 빈 생성자는이 사실을 문서화합니다 .

그러나 C ++의 목표는 가능한 한 모든 유효한 C 프로그램도 유효한 C ++ 프로그램이었습니다 (더 이상 목표가 유효하지 않으며 C의 C ++ 로의 진화는 더 이상 보유하지 않음을 의미합니다). ).

이 중 하나 개 효과는 간 기능의 중복이었다 structclass. 전자는 C 방식으로 작업을 수행하고 (기본적으로 모든 것이 공개됨) 후자는 좋은 OO 방식으로 작업을 수행합니다 (기본적으로 비공개 인 경우 개발자는 원하는 것을 공개적으로 공개합니다).

다른 하나는 C struct에 생성자가 없기 때문에 생성자를 가질 수없는 C가 C ++에서 유효하기 위해서는 C ++에서이를 보는 의미가 있어야한다는 것입니다. 따라서 생성자가없는 것은 변형을 적극적으로 보장하는 OO 관행에 위배되지만 C ++은 빈 본문이있는 것처럼 작동하는 기본 매개 변수가없는 생성자가 있음을 의미했습니다.

모든 C structs는 이제 유효한 C ++이었습니다 structs. (이것은 classes마치 매개 변수가없는 단일 생성자가있는 것처럼 외부에서 모든 것을 처리하는 C ++ 과 동일하다는 것을 의미 합니다.

그러나 생성자를 classor struct에 넣은 경우 C 방식이 아닌 C ++ / OO 방식으로 작업을 수행했으며 기본 생성자가 필요하지 않았습니다.

간결한 역할을 했으므로 호환성이 불가능한 경우에도 사람들은 계속 사용했습니다 (C가 아닌 다른 C ++ 기능을 사용했습니다).

따라서 Java가 여러 가지 방법으로 C ++을 기반으로하고 나중에 C # (여러 가지 방법으로 C ++ 및 Java를 기반으로)을 도입했을 때, 이미 코더가 익숙한 것처럼이 접근법을 유지했습니다.

Stroustrup은 C ++ 프로그래밍 언어로 이에 대해 썼으며 C ++ 의 디자인과 진화 에서 언어의“왜”에 더 중점을 두었습니다 .

=== 원래 답변 ===

이것이 일어나지 않았다고 가정 해 봅시다.

클래스가없는 상태를 의미있는 상태로 만들 수 없기 때문에 매개 변수가없는 생성자를 원하지 않는다고 가정 해 봅시다. 실제로 이것은 structC #에서 발생할 수있는 일입니다 (그러나 C #에서 0을 null struct로 의미있게 사용할 수 없다면 공개적으로 볼 수없는 최적화를 사용하는 것이 가장 좋습니다. struct) 를 사용하여 디자인 결함 .

클래스가 불변을 보호 할 수있게하려면 특별한 removeDefaultConstructor키워드 가 필요 합니다. 최소한 호출 코드가 기본값을 호출하지 않도록 개인 매개 변수없는 생성자를 만들어야합니다.

언어를 좀 더 복잡하게 만듭니다. 하지 않는 것이 좋습니다.

대체로 생성자를 추가하는 것으로 생각하지 않는 것이 가장 좋습니다. 아무것도하지 않는 매개 변수가없는 생성자를 추가하기 위해 생성자가없는 구문 설탕으로 생각하는 것이 좋습니다.


답변

객체 생성을 제어하기 위해 직접 작업을 수행하지 않으면 기본 매개 변수가없는 생성자가 추가됩니다. 제어 할 단일 생성자를 만든 후에는 컴파일러가 “백 오프”하여 모든 권한을 갖습니다.

이 방법이 아닌 경우 매개 변수가있는 생성자를 통해서만 객체를 생성 할 수있게하려면 기본 생성자를 비활성화하는 명시적인 방법이 필요합니다.


답변

컴파일러의 편의 기능입니다. 매개 변수를 사용하여 생성자를 정의하지만 매개 변수없는 생성자를 정의하지 않으면 매개 변수없는 생성자를 허용하지 않을 가능성이 훨씬 높습니다.

이것은 빈 생성자로 초기화하는 것이 의미가없는 많은 객체의 경우입니다.

그렇지 않으면 제한하려는 각 클래스에 대해 개인 매개 변수없는 생성자를 선언해야합니다.

제 생각에는 매개 변수가 필요한 클래스의 매개 변수가없는 생성자를 허용하는 것은 좋은 스타일이 아닙니다.


답변

나는 다른 질문을해야한다고 생각합니다. 다른 생성자를 정의하지 않은 경우 기본 생성자를 선언 해야하는 이유는 무엇입니까?

비 정적 클래스에는 생성자가 필수입니다.
따라서 생성자를 정의하지 않은 경우 생성 된 기본 생성자는 C # 컴파일러의 편리한 기능이며 생성자가 없으면 클래스가 유효하지 않습니다. 따라서 아무것도하지 않는 생성자를 암시 적으로 생성하는 데 아무런 문제가 없습니다. 빈 생성자를 사용하는 것보다 확실히 더 깨끗해 보입니다.

이미 생성자를 정의한 경우 클래스가 유효하므로 컴파일러에서 기본 생성자를 원한다고 가정해야하는 이유는 무엇입니까? 원하지 않으면 어떻게합니까? 컴파일러에게 기본 생성자를 생성하지 않도록 지시하는 속성을 구현 하시겠습니까? 나는 그것이 좋은 생각이라고 생각하지 않습니다.


답변

기본 생성자는 클래스에 생성자가없는 경우에만 생성 할 수 있습니다. 컴파일러는이를 백업 메커니즘으로 만 제공하도록 작성되었습니다.

매개 변수화 된 생성자가있는 경우 기본 생성자를 사용하여 오브젝트를 작성하지 않을 수 있습니다. 컴파일러가 기본 생성자를 제공했다면 인수없이 객체가 생성되지 않도록하기 위해 인수없는 생성자를 작성하고 비공개로 만들어야했습니다.

또한 기본 생성자를 비활성화하거나 ‘비공개’하여 잊어 버릴 수있는 잠재적 인 기능 오류가 발생할 가능성이 높아집니다.

이제 객체를 기본 방식으로 만들거나 매개 변수를 전달하여 인수가없는 생성자를 명시 적으로 정의해야합니다. 이것은 강력하게 확인되고 컴파일러는 달리 불평하여 허점을 보장하지 않습니다.