2000 년대에 제 동료는 공개 방법을 가상 또는 추상적으로 만드는 것이 반 패턴이라고 말했습니다.
예를 들어, 그는 잘 설계되지 않은 다음과 같은 클래스를 고려했습니다.
public abstract class PublicAbstractOrVirtual
{
public abstract void Method1(string argument);
public virtual void Method2(string argument)
{
if (argument == null) throw new ArgumentNullException(nameof(argument));
// default implementation
}
}
그는 말했다
- 구현
Method1
하고 재정의 하는 파생 클래스의 개발자Method2
는 인수 유효성 검사를 반복해야합니다. - 경우에 기본 클래스의 개발자의 사용자 정의 부분 주위에 무언가를 추가하기로 결정
Method1
또는Method2
후, 그는 그것을 할 수 없습니다.
대신 내 동료가이 접근법을 제안했습니다.
public abstract class ProtectedAbstractOrVirtual
{
public void Method1(string argument)
{
if (argument == null) throw new ArgumentNullException(nameof(argument));
this.Method1Core(argument);
}
public void Method2(string argument)
{
if (argument == null) throw new ArgumentNullException(nameof(argument));
this.Method2Core(argument);
}
protected abstract void Method1Core(string argument);
protected virtual void Method2Core(string argument)
{
// default implementation
}
}
그는 공개 방법 (또는 속성)을 가상 또는 추상으로 만드는 것이 필드를 공개하는 것만 큼 나쁘다고 말했습니다. 필드를 속성에 래핑하면 나중에 필요한 경우 해당 필드에 대한 액세스를 가로 챌 수 있습니다. 공용 가상 / 추상 멤버에도 동일하게 적용됩니다. ProtectedAbstractOrVirtual
클래스에 표시된대로 멤버를 래핑 하면 기본 클래스 개발자가 가상 / 추상 메소드로 이동하는 모든 호출을 가로 챌 수 있습니다.
그러나 나는 이것을 설계 지침으로 보지 않습니다. 심지어 Microsoft조차도 따르지 않습니다 Stream
. 클래스를 살펴보고 이를 확인하십시오.
그 지침에 대해 어떻게 생각하십니까? 이해가 되나요, 아니면 API를 지나치게 복잡하게 생각하십니까?
protected
추상 클래스의 개인 멤버를 파생 클래스에 노출하려는 경우 가장 유용합니다. 어쨌든, 나는 당신의 친구의 의견에 대해 특별히 걱정하지 않습니다. 특정 상황에 가장 적합한 액세스 수정자를 선택하십시오.
virtual
은 선택적 대체를 허용합니다. 재정의되지 않을 수 있으므로 메서드가 공개되어야합니다. 메소드를 작성하면 메소드abstract
를 대체해야합니다. 문맥protected
에서 특별히 유용하지 않기 때문에 아마도이어야합니다public
.