2009-07-23 3 views
16
인터페이스를 구현 내가 추상 클래스가

, AbsClass, ICLASS와 추상 클래스에서 파생되는 클래스의 속성에 설정 접근을 추가. IClass에는 접근 자 가져 오기와 함께 몇 가지 속성이 있습니다. AbsClassIClass의 속성을 AbsClass에서 파생되는 클래스로 정의되는 추상 속성으로 구현합니다.만 get 접근

그래서 에서 AbsClass를 도출의 모든 클래스는 가져 오기 접근과 같은 특성을 갖는 의해 ICLASS을 만족해야합니다. 그러나 경우에 따라 IClass에서 속성에 설정된 접근자를 추가 할 수 있기를 원합니다. 그러나 나는이 오류

AbsClass.Bottom가 재정의 set 접근이 없기 때문에 ConcClassA.Bottom.Set는 무시할 수 없습니다

참조를 얻을 set 접근과 에 AbsClass을 추상적 인 속성을 재정의하려고하면 ConcClassA.

IClass 인터페이스 만 구현하고 AbsClass를 상속하지 않는 클래스가있는 경우 문제가있는 세트 접근자를 추가 할 수 있습니다. 아래 ConcClassB을 참조하십시오.

나는 AbsClass 대신 직접 AbsClass를 파생시킬 때마다 IClass를 구현할 수 있습니다. 그러나 나는 내 AbsClass가 IClass 일 필요가 있음을 알고 있으므로 계층 구조에서 상위 클래스를 지정하려고합니다.

public interface IClass 
{ 
    double Top 
    { 
     get; 
    } 
    double Bottom 
    { 
     get; 
    } 
} 

abstract class AbsClass:IClass 
{ 
    public abstract double Top 
    { 
     get; 
    } 

    public abstract double Bottom 
    { 
     get; 
    } 
} 



class ConcClassA : AbsClass 
{ 
    public override double Top 
    { 
     get { return 1; } 
    } 

    public override double Bottom 
    { 
     get { return 1; } 

     //adding a Set accessor causes error: 
     //ConcClassA.Bottom.Set cannot override because AbsClass.Bottom does not have an overridable set accessor 

     //set { } 
    } 

} 

class ConcClassB : IClass 
{ 
    public double Top 
    { 
     get { return 1; } 
     //added a set accessor to an interface does not cause problem 
     set { } 
    } 
    public double Bottom 
    { 
     get { return 1; } 
    } 
} 

업데이트 그래서 내가 추상적 예를 사용하여 다음 대신 할 노력하고있어 정확하게 설명 할 경우이 더 이해가 것이라 생각합니다. 저는 건축 회사에서 일하면서 건축 설계 프로젝트와 관련된 비즈니스 오브젝트입니다.

나는 프로젝트의 한 유형을 나타내는 추상 클래스 RhNodeBuilding을 가지고 있습니다. 바닥을 가질 수있는 기능과 같은 몇 가지 일반적인 기능이 있으며 RhNodeBuilding에 정의되어 있습니다. RhNodeBuilding은 또한 더 큰 프로젝트 트리 구조의 일부가 될 수있는 또 다른 추상 클래스를 상속합니다.

RhNodeBuilding 모든 건물을 제공 할 수 있어야 읽기 전용 속성의 수를 정의하는 인터페이스 IBuilding에서 구현 등 TopElevation, BottomElevation, 높이, NumberOfFloors 등 등 .기타..RhNodeBuilding에서 파생되지는 않지만 여전히 IBuilding을 구현해야하는 다른 건물 유형이 있습니다. MassBuildingFootPrintBuilding :

는 지금은 RhNodeBuilding에서 파생 된 두 가지 유형이있다. MassBuilding은 사용자가 만든 3D 모양으로 정의됩니다. 해당 모양은 TopElevationBottomElevation으로 해당 속성을 통해 액세스 할 수 있어야하지만 속성을 변경하여 3D 볼륨을 편집하면 안됩니다.

FootPrintBuilding은 닫힌 커브와 해당 커브를 돌출시키는 높이 범위로 정의됩니다. 따라서 클래스가 현재 고도가 무엇인지를 반환 할 수있을뿐만 아니라 이러한 고도 또한 높이 범위를 다시 정의 할 수 있어야합니다.

요약하면. 모든 건물 (IBuildings)는 TopElevationBottomElevation를 반환 할 수 있어야하지만, 모든 건물은 TopElevation 또는 BottomElevation가 직접 설정할 수 있도록한다. 모든 RhNodeBuildings은 수 직접 BottomElevationTopElevation을 설정할 수 IBuildings하고, 또는 필요하지 않을 수도 있습니다 RhNodeBuilding에서 파생 클래스입니다.

public interface IBuilding 
{ 
    double Top 
    { 
     get; 
    } 
    double Bottom 
    { 
     get; 
    } 
} 

abstract class RhNodeBuilding:IBuilding 
{ 
    public abstract double Top 
    { 
     get; 
    } 

    public abstract double Bottom 
    { 
     get; 
    } 
} 



class MassBuilding: AbsClass 
{ 

    //mass building only returns Top and Bottom properties so it works fine 
    public override double Bottom 
    { 
     get { return 1; } 
    } 

    public override double Top 
    { 
     get { return 1; } 
    } 

} 


class FootPrintBuilding: AbsClass 
{ 
    //Top and Bottom of FootPrintBuilding can both be retrieved and set 
    public override double Top 
    { 
     get { return 1; } 
     //adding a Set accessor causes error: 
     //cannot override because RhNodeBuilding.Top does not have an overridable set accessor 

     //set { } 
    } 

    public override double Bottom 
    { 
     get { return 1; } 

     //adding a Set accessor causes error: 
     //cannot override because RhNodeBuilding.Bottom does not have an overridable set accessor 

     //set { } 
    } 

} 

는 최선의 선택이 RhNodeBuilding이 IBuilding을 구현하지하는 것입니다처럼 지금 보인다 아니라 IBuilding을 구현 RhNodeBuilding에서 파생 된 모든 클래스가 있습니다. 그런 식으로 속성을 정의 할 수 있습니다 IBuilding보다는 직접 오버라이드.

abstract class AltRhNodeBuilding 
{ 
    public abstract double Top 
    { 
     get; 
    } 
} 


class AltFootPrintBuilding: IClass 
{ 
    public override double Top 
    { 
     get { return 1; } 

     //Can't add set access to overridden abstract property 
     set { } 
    } 

    //No problem adding set accessor to interface property 
    public double Bottom 
    { 
     get { return 1; } 
     set { } 
    } 
} 
+0

"이 속성은 때때로 읽기 전용이지만 때로는 그렇지 않다"는 말로 인터페이스 "계약"을 위반하지 않습니까? 아마도 읽기 전용이 필요한 클래스와 읽기/쓰기가 필요한 클래스를 허용하기 위해 인터페이스를 분리해야합니다 (예 : 다른 인터페이스로). –

+0

속성 접근자가 없다는 것은 해당 속성이 모든 사람에게 읽기 전용임을 의미하지는 않습니다 (즉, 변경 불가능하고 값이 변경되지 않음). 이는 해당 속성을 사용하는 클라이언트의 속성이 읽기 전용임을 의미합니다. 그래서, 아니, 그것은 계약 변경을 깨뜨리는 것이 아닙니다. 그것은 단지 C#/CLR 제한입니다. –

+0

동의, 인터페이스 계약은 구현하지 않아도되는 것이 아니라 구현해야하는 것을 지정합니다. –

답변

10

이것은 속성이 실제로 가상이 아니기 때문에 작동합니다. 접근 자 메서드는 다음과 같습니다. 따라서 기본 클래스에 하나가 없으면 set을 재정의 할 수 없습니다.

수행 할 수있는 작업은 기본 클래스 구현 인 을 덮어 쓰고 새롭게 읽기/쓰기 속성을 제공하는 것입니다.

class AbsClassB : AbsClass 
{ 
    public override double Top { get { return ((ConcClassB)this).Top } } 
    public override double Bottom { get { return ((ConcClassB)this).Bottom } } 
} 


class ConcClassB : AbsClassB 
{ 
    new public double Top 
    { 
     get { ... } 
     set { ... } 
    } 

    new public double Bottom 
    { 
     get { ... } 
     set { ... } 
    } 
} 

가 더 좋은 아이디어를 잘 AbsClass에 보호 된 가상 메서드를 정의하는, 그리고 측면에서 Top.getBottom.get을 구현하는 것이 : 나는 계층 구조에 추가 클래스를 도입하지 않고이 작업을 수행 할 수있는 방법을 알고하지 않습니다 그 방법.그럼 당신은 별도의 클래스를 필요로하지 않고, ConcClassB에 직접 메소드를 오버라이드 (override)하고 속성을 그림자 수 있습니다 : 당신이 공공 setter 메소드를 가지고이 구현 클래스를 원하는 것이 이유에 가지 궁금

abstract class AbsClass : IClass 
{ 
    public double Top 
    { 
     get { return GetTop(); } 
    } 

    public double Bottom 
    { 
     get { return GetBottom(); } 
    } 

    protected abstract double GetTop(); 

    protected abstract double GetBottom(); 
} 

class ConcClassB : AbsClass 
{ 
    new public double Top 
    { 
     get { ... } 
     set { ... } 
    } 

    new public double Bottom 
    { 
     get { ... } 
     set { ... } 
    } 

    protected override double GetTop() 
    { 
     return Top; 
    } 

    protected override double GetBottom() 
    { 
     return Bottom; 
    } 
} 
+0

하지만 ConcClassB는 AbsClass –

+0

에서 파생되어야합니다. 인터페이스를 확장하면 냄새가 나는 추상적 인 정의를 사용해야합니다. 결국 당신은 콘크리트 클래스의 인수/변수를 선언 할 필요가 있습니다. -이 경우에는 피할 수 있거나, 추상 형식을 cst로 선언하여 구체적인 유형을 선언해야합니다. 새로운 작업. 네가 liskov를 위반했을 것이기 때문에 똑같이 나쁘다. 예를 들면 다음과 같이 동작을 제한 할 수있다. IList (T 없음)를 구현하지만 없음 유형 지정 메소드를 "숨김"(명시 적 구현)으로 나열하는 목록 –

+0

그래, 내 잘못 - 질문을 잘못 읽었습니다. 업데이트 된 버전을 확인하십시오. –

0

그 공용 인터페이스의 일부가 아닙니다. 당신이 실제로 이들이 대중보다 더 제한되기를 원하는 것 같아요?

이 외에도이 접근 방법으로 문제를 생각해 보는 데 어려움을 겪고 있습니다. 그들은 수퍼 클래스에서 모든 속성을 "숨길"는 있지만 어쨌든 수퍼 클래스에는 속성 설정자가 없으므로 괜찮습니다. 그것은 가장 간단한 해결 방법이 될 것 같습니다.

+0

나는 내 질문에 내가하고있는 것에 대한 덜 추상적 인 설명을 추가했다. –

+0

재정의 된 getter가있는 속성에 * private * setter를 추가하려고하면이 오류가 발생합니다. – jwg

-13

전역 변수를 사용하십시오.

관련 문제