2008-11-07 3 views
4

나는 Ship이라는 클래스와 Lifeboat메소드를 숨겨 프로그래머가 호출하지 않지만 코드에서 사용할 수 있도록하려면 어떻게합니까?

이라는 클래스를 가지고있다. 구명 보트는 배를 상속한다.

Ship에는 저장 전에 호출되는 Validate()이라는 메서드가 들어 있으며 Validate에서 호출하는 FurtherValidate()이라는 추상 메서드가 있습니다. 이것이 존재하는 이유는베이스에서 validate를 호출 할 때 상속 된 클래스의 유효성을 검사하기 때문입니다. 그래서 우리는

public class Ship 

public bool Validate() 
{ 
    //validate properties only found on a ship 

    FurtherValidate(); 
} 

public abstract bool FurtherValidate(); 

이 그래서 Lifeboat

public override bool FurtherValidate() 
{ 
    //validate properties only found on a lifeboat 
} 

을 가지고이 Ship를 구현하는 사람이 아니라 자신의 클래스에 대한 자신의 유효성 검사를 제공 할 필요가 의미하고 기본 선박으로 저장 호출 할 보장합니다. 차례로 계승 된 유효성 검사를 호출하는 Validate()이 호출됩니다.

상속받은 클래스가 FurtherValidate()을 구현하도록 강제하지만, 프로그래머가 결코 FurtherValidate()을 호출 할 수 없도록하려면 어떻게 다시 할 수 있습니까? 현재 Lifeboat.FurtherValidate()을 호출 할 수 있으며 어떻게 든이를 막으려 고합니다.

답변

4

당신이 묘사하는 정확한 시나리오는 불가능합니다. FurtherValidate 메서드에 대한 액세스는 protected 액세스 한정자를 사용하여 파생 클래스로만 제한 할 수 있습니다. internal 수정자를 사용하여 동일한 어셈블리의 클래스로만 제한 할 수도 있지만, 프로그래머가 파생 클래스를 작성하면 원하는 언제든지 AdditionalValidate를 호출 할 수 있습니다. protected와 internal을 모두 사용하면 두 가지가 결합 된 것은 실제로 동일한 어셈블리에 정의 된 파생 클래스 또는 클래스로 제한된다는 것을 의미합니다.

[EditorBrowsable] 특성을 사용하는 것은 다른 프로그래머가 VS에서 올바른 옵션을 설정하지 않은 경우 IntelliSense에서 메서드를 숨기는 IDE 트릭입니다. 그러면 대부분의 사람들이 그것을 호출하지 못하게됩니다 (볼 수 없다면 존재하지 않습니다).

발신자가 누구인지를 조사하기 위해 리플렉션을 사용하여이를 달성 할 수는 있지만 이점에 비해 성능 비용이 너무 높을 것으로 생각됩니다.

+1

C#에서는 protected라고 표시된 클래스에 internal을 추가하면 범위를 좁히지 않고 표시 범위가 넓어집니다. 일리노이에서는 ProtectedOrInternal로 컴파일됩니다. 즉, 상속하는 모든 클래스에서이를 볼 수 있으며 어셈블리의 모든 클래스에서이를 볼 수 있습니다. IL에는 ProtectedAndInternal도 있지만 C#은 없습니다. –

+0

앞으로 좋은 방법으로 IDE 속성을 사용할 것입니다. 대단히 고마워요 – Robert

+0

예, 보호 및 내부를 모두 추가하면 가시성이 넓어집니다 ("보호 또는 내부"를 의미 함). –

1

public 대신 protected로 설정하면 최소한 외부 객체가이를 호출하지 못하도록합니다.

7
protected abstract bool FurtherValidate(); 

배송 및 구명정 만 볼 수 있습니다.

편집 : 구명 보트는 그것을 볼 수 있어야합니다. FurtherValidate이 보이지 않을 때 어떻게 재정의해야합니까? 나는 그것을 ValidateCore으로 바꿀 것이고, '핵심'부분은 아주 좋은 이유없이 호출되지 않아야 함을 의미한다.

추상적으로 보이지만 보이지 않게 만드는 것은 쉽지 않다고 생각합니다. 구명정에 대한 신념이 필요합니다.)

+0

그래도 구명정에서 호출 할 수 있습니다 – Marko

+0

맞습니까? 그는 서브 클래스가 외부 클래스가 메소드에 액세스하지 않고 메소드를 구현해야한다고 주장한다. 왜냐하면 슈퍼 클래스가 호출 할 때만 의미가 있기 때문이다. – cfeduke

+0

아니요, 그는 하위 클래스에서 구현해야하지만 Ship.Validate()를 호출하는 것 외에는 임의로 호출하지 않도록해야합니다. –

0

이 방법을 protected으로 표시하면 상속하는 클래스에서만 액세스 할 수 있습니다. 이것은 상속인이 다른 공개 메서드를 통해 메서드를 노출하는 것을 방지하지는 않지만 일반적으로 주요 관심사는 아닙니다.

3

가장 간단한 대답은 보호 된 방법 일 것입니다. 이것은 상속인이 호출 할 수는 있지만 공개적으로 사용할 수는 없습니다. 그러나 상속 클래스를 공개하는 방법을 변경하는 것을 막을 수있는 방법은 없습니다.

MoreValidate 메서드를 완전히 제거하고 모든 상속 클래스가 Validate를 재정의하고 원하는 경우 base.Validate()를 호출하는 경향이 있습니다. 이렇게하면 ship에서 상속받은 모든 클래스가 validate 메소드를보다 잘 제어 할 수 있습니다.

+0

이 시나리오의 문제는 재정의 된 Validate 메서드가 실제로 base.Validate()를 호출하는지 확인할 수있는 방법이 없다는 것입니다. 제시된 시나리오에서 OP는 항상 기본 Validate() 메서드가 호출되기를 원합니다. –

+0

추상 메서드를 사용하면 기본 Validate 메서드를 여전히 재정의 할 수 있기 때문에이를 보장 할 필요가 없습니다. 상속받은 클래스가 재정의하는 메소드가 여전히 목적을 충족시키는 지 확인하는 것은 상속 클래스의 책임이라고 생각합니다. –

+0

새로운 Validate 메소드로 기본 Validate 메소드를 숨길 수 있습니다. 새 키워드를 사용하지 않으면 컴파일러 경고가 표시되고 new 키워드를 사용하면 명시 적으로 메서드를 숨길 수 있습니다. –

-1

아마 당신이

+0

비공개로 설정하면 파생 클래스에서 완전히 숨겨져 다시 정의 할 수 없게됩니다. –

+0

보호됨? 그냥 추측 여기 –

7

짧은 대답은 민간 수정을 시도 할 수 있습니다, 당신은 그것을 파생 년대 클래스에서 파생 된 방법을 숨길 수 없습니다. 그러나 달성하려는 목표를 달성하기 위해 코드를 리팩토링 할 수 있습니다.

public class Ship 
{  
    public virtual bool Validate()  
    {   
     //validate properties only found on a ship 
     return true; 
    } 
} 
public class Lifeboat : Ship 
{ 
    public override bool Validate() 
    {  
     base.Validate();  
     // lifeboat specific code 
     return true; 
    } 
} 
+0

그 시나리오의 문제는 다음 overriden Validate 메서드가 실제로 base.Validate()를 호출하는지 확인할 수있는 방법이 없다는 것입니다. 제시된 시나리오에서 OP는 항상 기본 Validate() 메서드가 호출되기를 원합니다. –

+0

개발자가 Lifeboat.Validate()를 호출하는 경우 기본.Validate()가 호출됩니다. –

+0

오른쪽 ... 문제는 Lifeboat.Validate를 작성한 개발자가 base.Validate()에 대한 호출을 포함한다는 것을 보장 할 수있는 방법이 없다는 것입니다. –

2

보호가 올바른 방법입니다. 그러나 다른 상황에서는 editorbrowsableattribute을 사용하여 intellisense에서 메서드를 숨길 수 있습니다.여전히 전화를 걸 수 있지만 프로그램을 폭파시킬 수있는 뭔가를 호출하는 것을 개발자가 막을 수 있으며 일반적으로 커다란 설명문을 읽도록 강요합니다.

+0

그것은 훌륭한 제안입니다. –

+0

좋은 아이디어! BTW 나는이 질문이 얼마나 많은 대답을 얻었는지 놀라 울뿐입니다. – alvin

+0

EditorBrowsable 특성은 VS가 고급 멤버를 표시하도록 구성되지 않은 경우에만 IntelliSense에서 숨기는 IDE 트릭입니다 (기본값은 숨김). –

1

유효성 검사는 선박의 기능적 책임의 일부가 아니므로 여기에서 코드 냄새가 난다. 즉, 어쩌면 최상의 솔루션이 아닐 때 상속을 사용하여 문제를 해결하려고하는 것일 수도 있습니다. 검증 로직을 리팩터링하여 검증을 클래스에 주입하십시오. 이것은 도메인 객체 Ship의 관점에서 배가 유효하지 않으므로 외부에서 유효성이 검사되므로 더 잘 이해할 수 있습니다. 이 유효성 검사기가되도록하려면이어야하며 속성이 null이면 예외를 throw 할 수 있습니다.

protected IValidator FurtherValidation { private get; set; } 

public bool Validate() 
{ 
//validate properties only found on a ship 

    if (FurtherValidation == null) 
     throw new ValidationIsRequiredException(); 
    if (!FurtherValidation.IsValid(this)) 
     // logic for invalid state 
} 
+0

감사합니다 :).하지만 실제로는 배가 아닙니다. 시나리오는 질문에 대한 것입니다. 이 경우 개체는 모델의 일부이며 모델은 저장되기 전에이 인스턴스에서 자체의 유효성 검사를 담당합니다. – Robert

+0

나는 여전히 당신이 상속에 대한 구성에 기대다. 상속을 통해 문제를 깨끗하게 해결할 수 없다는 사실은 그것이 아마도 잘못된 솔루션이라는 사실을 나타냅니다. –

관련 문제