문제

보호된 멤버 변수를 사용해야 합니까?장점은 무엇이며 이로 인해 어떤 문제가 발생할 수 있습니까?

도움이 되었습니까?

해결책

보호된 멤버 변수를 사용해야 합니까?

상태를 숨기는 것에 대해 얼마나 까다로운지에 따라 다릅니다.

  • 내부 상태 유출을 원하지 않는다면 모든 멤버 변수를 비공개로 선언하는 것이 좋습니다.
  • 하위 클래스가 내부 상태에 액세스할 수 있는지 크게 신경 쓰지 않는다면 protected로도 충분합니다.

개발자가 클래스를 하위 클래스로 분류하면 클래스를 완전히 이해하지 못하기 때문에 엉망이 될 수 있습니다.공용 인터페이스 이외의 개인 멤버를 사용하면 작업이 수행되는 방식에 대한 구현 특정 세부 정보를 볼 수 없으므로 나중에 변경할 수 있는 유연성이 제공됩니다.

다른 팁

요즘 일반적인 느낌은 파생 클래스와 해당 기반 사이에 과도한 결합을 유발한다는 것입니다.

보호된 메서드/속성에 비해 특별한 이점이 없으며(옛날에는 약간의 성능 이점이 있었을 수도 있음), 현재는 그렇지 않은 매우 깊은 상속이 유행했던 시대에 더 많이 사용되었습니다.

일반적으로 어떤 것이 의도적으로 공개되지 않으면 비공개로 설정합니다.

파생 클래스에서 해당 개인 변수나 메서드에 액세스해야 하는 상황이 발생하면 이를 개인에서 보호로 변경합니다.

이런 일은 거의 발생하지 않습니다. 저는 상속을 전혀 좋아하지 않습니다. 상속은 대부분의 상황을 모델링하는 데 특히 좋은 방법이 아니기 때문입니다.어쨌든 걱정하지 말고 계속하세요.

나는 이것이 대부분의 개발자들에게 괜찮다고 말하고 싶습니다(아마도 가장 좋은 방법일 것입니다).

문제의 간단한 사실은, 1년 후에 다른 개발자가 나타나서 비공개 멤버 변수에 액세스해야 한다고 결정하면 코드를 편집하고 보호됨으로 변경한 다음 비즈니스를 계속할 것입니다.

이에 대한 유일한 실제 예외는 바이너리 dll을 블랙박스 형식으로 제3자에게 배송하는 사업에 종사하는 경우입니다.이는 기본적으로 Microsoft, 'Custom DataGrid Control' 공급업체 및 확장성 라이브러리와 함께 제공되는 몇 가지 다른 대규모 앱으로 구성됩니다.당신이 해당 범주에 속하지 않는 한, 이런 종류의 일에 대해 걱정하는 데 시간/노력을 투자할 가치가 없습니다.

일반적으로 보호된 멤버 변수를 사용하는 코드를 완전히 제어할 수 있는 드문 경우에는 보호된 멤버 변수를 유지하겠습니다.공개 API를 생성하는 경우 절대로 사용하지 않을 것입니다.아래에서는 멤버 변수를 개체의 "속성"으로 참조합니다.

당신의 슈퍼클래스는 다음과 같습니다 할 수 없다 private-with-accessor가 아닌 보호된 멤버 변수를 만든 후에 수행하십시오.

  1. 속성을 읽는 동안 즉시 값을 게으르게 생성합니다.보호된 getter 메서드를 추가하면 값을 느리게 생성하고 다시 전달할 수 있습니다.

  2. 속성이 수정되거나 삭제된 시기를 알 수 있습니다.이는 슈퍼클래스가 해당 변수의 상태에 대해 가정할 때 버그를 유발할 수 있습니다.변수에 대해 보호된 setter 메서드를 만들면 해당 제어가 유지됩니다.

  3. 변수를 읽거나 쓸 때 중단점을 설정하거나 디버그 출력을 추가하세요.

  4. 이를 사용할 수 있는 모든 코드를 검색하지 않고 해당 멤버 변수의 이름을 바꿉니다.

일반적으로 보호된 멤버 변수를 만드는 것을 권장하는 경우는 드물다고 생각합니다.몇 시간 후에 보호된 변수를 수정한 다른 코드의 버그를 추적하는 것보다 getter/setter를 통해 속성을 노출하는 데 몇 분을 소비하는 것이 더 좋습니다.그뿐만 아니라 종속 코드를 손상시키지 않고 향후 기능(예: 지연 로딩)을 추가하지 않아도 됩니다.지금 하는 것보다 나중에 하는 것이 더 어렵습니다.

디자인 수준에서는 보호 속성을 사용하는 것이 적절할 수 있지만 구현 시 접근자/변경자 메서드가 아닌 보호 멤버 변수에 매핑하는 데는 이점이 없습니다.

보호된 멤버 변수는 기본 클래스 클래스의 내부 상태에 대한 클라이언트 코드(하위 클래스) 액세스를 효과적으로 허용하므로 상당한 단점이 있습니다.이는 기본 클래스가 불변성을 효과적으로 유지하는 것을 방지합니다.

같은 이유로 보호된 멤버 변수는 상수가 보장되지 않거나 단일 스레드로 제한되지 않는 한 안전한 다중 스레드 코드 작성을 훨씬 더 어렵게 만듭니다.

접근자/변경자 방법은 유지 관리 시 훨씬 더 많은 API 안정성과 구현 유연성을 제공합니다.

또한 OO 순수주의자라면 개체는 상태를 읽거나 설정하는 것이 아니라 메시지를 보내 공동 작업/통신합니다.

그 대가로 그들은 이점을 거의 제공하지 않습니다.다른 사람의 코드에서 반드시 제거할 필요는 없지만 직접 사용하지는 않습니다.

나에게 있어서 가장 중요한 문제는 일단 변수를 보호하도록 설정하면 클래스의 어떤 메서드도 보호되도록 허용할 수 없다는 것입니다. 의존하다 하위 클래스는 항상 값을 범위 밖에 배치할 수 있기 때문에 해당 값이 범위 내에 있어야 합니다.

예를 들어, 렌더링 가능한 객체의 너비와 높이를 정의하는 클래스가 있고 해당 변수를 보호하도록 설정하면 종횡비에 대한 가정을 할 수 없습니다.

비판적으로 나는 할 수 있다 절대 코드가 라이브러리로 출시되는 순간부터 언제든지 이러한 가정을 하십시오. 종횡비를 유지하기 위해 설정기를 업데이트하더라도 변수가 설정기를 통해 설정되거나 기존 코드의 게터를 통해 액세스된다는 보장이 없기 때문입니다.

내 클래스의 하위 클래스도 변수 값을 강제할 수 없기 때문에 이러한 보장을 선택할 수 없습니다. 그게 서브클래스의 전부라고 해도.

예로서:

  • 너비와 높이가 보호된 변수로 저장되는 직사각형 클래스가 있습니다.
  • 내 컨텍스트 내에서 명백한 하위 클래스는 "DisplayedRectangle" 클래스입니다. 유일한 차이점은 너비와 높이를 그래픽 디스플레이에 유효한 값으로 제한한다는 것입니다.
  • 하지만 지금은 그게 불가능해요, 내 DisplayedRectangle 클래스 이후 할 수 없다 하위 클래스가 값을 직접 재정의할 수 있으면서도 여전히 DisplayedRectangle로 처리되므로 해당 값을 실제로 제한합니다.

변수를 비공개로 제한함으로써 setter 또는 getter를 통해 원하는 동작을 시행할 수 있습니다.

대부분의 경우 protected를 사용하는 것은 클래스의 캡슐화를 어느 정도 깨뜨릴 수 있기 때문에 위험하며, 잘못 설계된 파생 클래스로 인해 캡슐화가 깨질 수도 있습니다.

하지만 좋은 예가 하나 있습니다.일종의 일반 컨테이너를 사용할 수 있다고 가정해 보겠습니다.내부 구현과 내부 접근자가 있습니다.하지만 해당 데이터에 대해 최소한 3개의 공개 액세스를 제공해야 합니다.지도, hash_map, 벡터형.그러면 다음과 같은 결과가 나타납니다.

template <typename T, typename TContainer>
class Base
{
   // etc.
   protected
   TContainer container ;
}

template <typename Key, typename T>
class DerivedMap     : public Base<T, std::map<Key, T> >      { /* etc. */ }

template <typename Key, typename T>
class DerivedHashMap : public Base<T, std::hash_map<Key, T> > { /* etc. */ }

template <typename T>
class DerivedVector  : public Base<T, std::vector<T> >        { /* etc. */ }

저는 이런 종류의 코드를 사용한 지 한 달도 채 되지 않았습니다(그래서 코드는 메모리에서 나온 것입니다).몇 가지 생각 끝에 저는 일반 Base 컨테이너가 추상 클래스여야 한다고 생각합니다. 비록 그것이 꽤 잘 작동할 수 있다고 하더라도 Base를 직접 사용하는 것은 너무 고통스러울 것이기 때문에 금지되어야 합니다.

요약 따라서 파생 클래스에서 사용하는 보호된 데이터가 있습니다.하지만 우리는 Base 클래스가 추상 클래스여야 한다는 사실을 고려해야 합니다.

요컨대 그렇습니다.

보호된 멤버 변수를 사용하면 모든 하위 클래스는 물론 동일한 패키지의 모든 클래스에서 변수에 액세스할 수 있습니다.이는 특히 읽기 전용 데이터의 경우 매우 유용할 수 있습니다.그러나 보호된 멤버 변수의 사용은 개인 멤버 변수와 몇 개의 getter 및 setter를 사용하여 복제될 수 있기 때문에 이것이 필요하다고 생각하지 않습니다.

"Exceptional C ++"의 항목 24에서 각주 중 하나에서 Sutter Goes "레코드를 위해서는"공개 또는 보호 된 멤버 변수가있는 클래스를 작성하지 않을 것입니다.오른쪽?(일부 라이브러리에서 설정한 좋지 않은 예에 관계없이)"

.Net 액세스 수정자에 대한 자세한 정보 여기로 가세요

보호된 멤버 변수에는 실제 장점이나 단점이 없으며 특정 상황에 무엇이 필요한지에 대한 질문입니다.일반적으로 멤버 변수를 비공개로 선언하고 속성을 통해 외부 액세스를 활성화하는 것이 허용됩니다.또한 일부 도구(예:일부 O/R 매퍼)는 객체 데이터가 속성으로 표시될 것으로 예상하고 공용 또는 보호된 멤버 변수를 인식하지 못합니다.그러나 하위 클래스(및 하위 클래스만)가 특정 변수에 액세스하기를 원한다는 것을 알고 있다면 해당 변수를 보호됨으로 선언하지 않을 이유가 없습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top