나는 찾고 있었고 이론적 인 차이점을 알고 있습니다.
- 공공의 모든 클래스 / 함수가 메소드 / 프로퍼티에 액세스 할 수 있습니다.
- 보호 이 클래스와 하위 클래스 만 메소드 / 속성에 액세스 할 수 있습니다.
- 개인 – 만이 클래스는 메소드 / 속성에 액세스 할 수 있습니다. 심지어 상속되지도 않습니다.
그게 다 괜찮습니다. 문제는 그들 사이 의 실제 차이점은 무엇입니까? 언제 사용 private
하고 언제 사용 protected
하시겠습니까? 이 표준에 대해 표준 또는 수용 가능한 모범 사례가 있습니까?
지금까지 상속과 다형성의 개념을 유지하기 public
위해 외부에서 액세스 해야하는 모든 것 (생성자 및 기본 클래스 기능과 같은)과 protected
내부 메서드 (논리, 도우미 메서드 등)에 사용합니다. 내가 올바른 길을 가고 있습니까?
(이 질문은 저를위한 것이므로이 질문과 같은 질문을 보지 못했기 때문에 나중에 참조 할 수 있습니다).
답변
아니요, 당신은 올바른 길을 가고 있지 않습니다. 경험상 가장 좋은 방법은 모든 것을 가능한 한 비밀로 만드는 것입니다. 이를 통해 클래스를보다 캡슐화 할 수 있으며 클래스를 사용하는 코드에 영향을주지 않고 클래스 내부를 변경할 수 있습니다.
클래스를 상속 가능하도록 디자인하는 경우 서브 클래스에서 재정의하고 액세스 할 수있는 항목을 신중하게 선택하고 보호되도록합니다 (및 액세스 가능하지만 재정의 할 수 없도록하려면 Java에 대해 이야기하십시오). 그러나 클래스의 서브 클래스를 갖도록 허용하고 보호 된 필드 또는 메소드가있는 경우이 필드 또는 메소드는 클래스의 공용 API의 일부이므로 서브 클래스를 중단하지 않고 나중에 변경할 수 없습니다.
상속되지 않는 클래스는 최종적으로 작성해야합니다 (Java). 단위 테스트를 위해 일부 액세스 규칙 (비공개, 최종, 비 최종)을 완화 할 수 있지만 문서화 한 다음 방법이 보호 되어도 무시되지 않아야한다는 점을 분명히해야합니다.
답변
여기서는 주로 메소드 액세스에 대해 이야기하고 있으며 클래스 가 멤버 액세스가 아닌 최종 클래스로 표시되는 정도는 조금 적습니다 .
오래된 지혜
“좋은 이유가없는 한 비공개로 표시하십시오.”
오픈 소스가 개발자 라이브러리 공간과 VCS / 종속성 관리 시스템을 지배하기 전까지는 며칠 만에 이해가되었습니다. Github, Maven 등 덕분에 하이퍼 콜라보레이션이되었습니다. 그 당시에는 라이브러리를 활용할 수있는 방법을 제한하여 돈을 벌었습니다. 나는 아마도이 “모범 사례”를 엄격히 고수하면서 경력의 처음 8 년 또는 9 년을 보냈다.
오늘 나는 그것이 나쁜 조언이라고 믿습니다. 때로는 메소드를 private 또는 class final로 표시하는 데 합리적인 주장이 있지만, 매우 드물고 심지어 개선되지 않는 경우가 있습니다.
넌 해본 적 있니:
- 상속 및 몇 줄의 코드로 해결할 수있는 버그가있는 라이브러리 등에 실망하거나 놀랐거나 상처를 받았지만 비공개 / 최종 방법과 클래스로 인해 절대로 올 수없는 공식 패치를 기다려야합니까? 나는 가지고있다.
- 저자가 상상 한 것과 약간 다른 유스 케이스에 라이브러리를 사용하고 싶었지만 개인 / 최종 방법 및 클래스로 인해 라이브러리를 사용할 수 없었습니까? 나는 가지고있다.
- 확장성에 과도하게 허용되는 라이브러리 등으로 인해 실망하거나 놀랐거나 다쳤습니까? 나는하지 않았다.
다음은 기본적으로 비공개 메소드 표시에 대해 들어 본 3 가지 합리화입니다.
합리화 # 1 : 안전하지 않으며 특정 방법을 무시할 이유가 없습니다.
필자가 작성한 특정 방법을 재정의해야하는지 여부에 대해 내가 틀린 횟수를 셀 수 없습니다. 몇 가지 인기있는 오픈 소스 라이브러리에서 작업 한 후, 사물을 표시하는 실제 비용을 어려운 방법으로 배웠습니다. 예상치 못한 문제 나 사용 사례에 대한 실질적인 해결책을 종종 제거합니다. 반대로, 나는 결코 16 년 이상 전문 개발에 API 안전과 관련된 이유로 개인이 아닌 보호 된 방법을 표시하는 것을 후회 . 개발자가 클래스를 확장하고 메서드를 재정의하기로 선택하면 의식적으로 “내가하는 일을 알고 있습니다”라고 말합니다. 생산성을 위해 충분해야합니다. 기간. 위험한 경우, 클래스 / 메소드 Javadocs에서주의하십시오. 맹목적으로 문을 닫지 마십시오.
기본적으로 보호되는 마킹 방법은 현대 SW 개발의 주요 문제 중 하나 인 상상력 상실의 완화입니다.
합리화 # 2 : 공용 API / Javadoc을 깨끗하게 유지
이것은 더 합리적이며 대상 고객에 따라 올바른 일이 될 수도 있지만 API를 “깨끗하게”유지하는 비용이 실제로 무엇인지 고려할 가치가 있습니다. 위에서 언급 한 이유로, 경우에 따라 기본적으로 보호되는 항목을 표시하는 것이 더 합리적입니다.
합리화 # 3 : 내 소프트웨어는 상용이므로 사용을 제한해야합니다.
이것은 합리적이지만 소비자는 매번 품질에 차이가 거의 없다고 가정하면서 덜 제한적인 경쟁자와 함께 갈 것입니다.
절대 말하지 마
나는 결코 메소드를 비공개로 표시하지 않는다고 말하고 있지 않다. 더 나은 경험 법칙은 “좋은 이유가 없다면 방법을 보호하는 것”입니다.
이 조언은 모듈로 나뉘어 진 라이브러리 또는 대규모 프로젝트에서 작업하는 사람들에게 가장 적합합니다. 더 작거나 더 많은 모 놀리 식 프로젝트의 경우 어쨌든 모든 코드를 제어하기 때문에 그다지 중요하지 않으며 필요할 때 / 필요할 때 코드의 액세스 수준을 쉽게 변경할 수 있습니다. 그럼에도 불구하고, 나는 여전히 똑같은 조언을 줄 것입니다 🙂
답변
개인 필드 학대 중지!
여기의 의견은 개인 필드 사용에 대해 압도적으로지지적인 것으로 보입니다. 글쎄, 다른 말이 있습니다.
사적인 분야는 원칙적으로 좋은가? 예. 그러나 황금률 이라는 말 은 확실 하지 않을 때 모든 것을 비공개로 만드는 것입니다 . 문제가 발생할 때까지 문제가 표시되지 않습니다. 내 의견으로 는 확실하지 않은 경우 필드를 보호 된 것으로 표시해야 합니다.
클래스를 확장하려는 두 가지 경우가 있습니다.
- 기본 클래스에 추가 기능을 추가하려고합니다
- 현재 패키지 외부에있는 기존 클래스를 수정하려고합니다 (일부 라이브러리에서)
첫 번째 경우 개인 필드에는 아무런 문제가 없습니다. 사람들이 사적 으로 학대한다는 사실 필드를 똥을 수정할 수 없다는 것을 알게되면 너무 실망 스럽습니다.
자동차를 모델링하는 간단한 라이브러리를 고려하십시오.
class Car {
private screw;
public assembleCar() {
screw.install();
};
private putScrewsTogether() {
...
};
}
도서관 저자는 내 도서관의 사용자가 assembleCar()
올바른 구현 세부 사항에 액세스해야 할 이유가 없다고 생각 했습니다. 나사를 비공개로 표시합시다.
글쎄, 저자는 틀렸다. assembleCar()
전체 클래스를 패키지에 복사하지 않고 메소드 만 수정하려면 운이 좋지 않습니다. 자신의 screw
필드 를 다시 작성해야 합니다. 이 자동차는 12 개의 나사를 사용하고 각각의 다른 개인 방법으로 사소한 초기화 코드가 포함되어 있으며이 나사는 모두 비공개로 표시되어 있다고 가정 해 봅시다. 이 시점에서 빨기 시작합니다.
예, 라이브러리 작성자가 더 나은 코드를 작성했을 수 있으므로 개인 필드에는 아무런 문제가 없습니다 . 개인 필드가 OOP 의 문제 라고 주장하지 않습니다. . 사람들이 사용할 때 문제가됩니다.
이야기의 교훈은 라이브러리를 작성하는 경우 사용자가 특정 필드에 액세스하려고하는지 알 수 없다는 것입니다. 확실하지 않으면 protected
나중에 모두 더 행복해질 수 있도록 표시하십시오 . 최소한 개인 필드를 남용하지 마십시오 .
나는 Nick의 대답을 매우지지합니다.
답변
나는 모든 클래스를 가능한 한 많이 잠그는 것에 대해 이야기 한 기사를 읽었습니다. 일부 데이터 또는 기능을 외부에 즉시 노출시킬 필요 가없는 한 모든 것을 최종적이고 비공개로 만드십시오 . 나중에 범위를 더 허용하기 쉽게 확장 할 수 있지만 다른 방법으로는 그렇지 않습니다. 우선 가능한 한 여러 가지로 만드는 것을 고려 final
사이의 선택 만들 것입니다 private
및 protected
훨씬 쉽게.
- 즉시 서브 클래스를 작성하지 않으면 모든 클래스를 최종 클래스로 만듭니다.
- 서브 클래 싱하고 즉시 재정의 할 필요가없는 한 모든 메소드를 최종으로 만드십시오.
- 메소드 본문 내에서 변경하지 않는 한 모든 메소드 매개 변수를 최종으로 지정하십시오.
이제 마지막 수업을 듣게되면 세상에 절대적으로 필요한 것이 없다면 모든 것을 비공개로 만드십시오.
서브 클래스가있는 클래스가 남아 있다면 모든 속성과 메소드를주의 깊게 검사하십시오. 먼저 해당 속성 / 메소드를 서브 클래스에 노출시키고 싶은지 고려하십시오. 그렇다면, 서브 클래스가 재정의 프로세스에서 특성 값 또는 메소드 구현을 엉망으로 만들면 오브젝트를 혼란스럽게 만들 수 있는지 고려하십시오. 가능하다면 클래스의 속성 / 메소드를 서브 클래스 (아이러니 한 소리)로부터 보호 하고 싶다면 비공개로 만드십시오. 그렇지 않으면 보호하십시오.
면책 조항 : Java로 프로그래밍하지 않았습니다. 🙂
답변
언제 사용 private
하고 언제 사용 protected
하시겠습니까?
개인 상속 은 IS-A 관계가 아닌 관계 측면에서 구현 된 것으로 생각할 수 있습니다 . 간단히 말해서 상속 클래스의 외부 인터페이스는 상속 클래스와 (보이는) 관계가 없으며,private
상속을 하여 Base 클래스가 제공하는 유사한 기능을 구현합니다.
Private Inheritance와 달리 Protected 상속 은 제한된 상속 형태로, 파생 클래스 IS-A 종류의 기본 클래스이며 파생 멤버의 액세스를 파생 클래스로만 제한하려고합니다.
답변
Paybill 클래스가 지불 청구를 처리하는 경우 캡슐화에 관한 모든 것입니다. 그렇다면 제품 클래스에서 청구 프로세스의 전체 프로세스, 즉 지불 방법을 지불하는 방법을 지불하는 방법이 필요한 이유는 무엇입니까? 다른 클래스들도 사용하는 사람들을 위해 공개하는 것 외에는 클래스를 확장하기위한 한계로만 보호됩니다. 당신이 madara uchiha이기 때문에 개인은 "limboo"
당신이 그것을 볼 수있는 것처럼 (단일 클래스 만 수업합니다).