2010-01-19 7 views
8

은 직원, 관리자 및 도우미 클래스를 고려 기본 클래스에서 속성을 억제 : 목표는이 같은 속성에 액세스하는 코드의 조각을 허용하는 것입니다 .NET 상속 :

public class Emp 
{ 
    public string Name { get; set; } 
    public Manager Manager { get; set; } 
    public Assistant Assistant { get; set; } 
} 

public class Manager : Emp 
{ 
} 

public class Assistant : Emp 
{ 
} 

:

var foo = new Manager(); 
var elmo = new Emp(); 
elmo.Manager = foo; 
elmo.Manager.Manager = new Manager(); 
//how to disallow access to Manager.Manager ? 

ManagerEmp을 상속하므로 .Manager.Assistant 속성을가집니다.

질문

.Manager.Assistant 속성을 제거하는 .NET의 상속 구현에 어떤 수정이 있습니까?

업데이트는 큰 응답, 모든 주셔서 감사합니다. 나는 Emp/Mgr의 단순화와 고안이이 질문에서 보여지기를 바랬다. 이 예제에서 상속은 또 다른 공통점 (예 : Person, 클래스가 이름, 생년월일 등을 공유하는 곳)으로 가져와야합니다. 입력 내용이 매우 만족 스럽습니다!

+0

나에게 디자인 문제와 같은 냄새가 난다. 관리자는 다른 관리자에게보고 할 수 있지만 보조자에게는 보조자가 없을 것입니다. 아마도 기지는 사람이어야합니다 ... – Walter

답변

9

이렇게하면 Liskov substitution principle을 위반하게되며 일반적으로 의심스러운 디자인입니다. 일반적으로 모든 서브 클래스는 기본 클래스가 될 모든 컨텍스트에서 사용할 수 있어야합니다. Manager.Manager이 없으면 Emp이 아니므로 해당 항목을 상속해서는 안됩니다.

2

아니요, 없습니다.

기본 클래스 속성을 virtual으로 설정 한 다음이를 재정 의하여 설정자에서 예외를 throw 할 수 있지만 컴파일 타임 오류를 줄 수는 없습니다. 결국,이 캐스팅을 방지하지 않습니다

public class ManagerEmployee : Emp {  
    public new ManagerEmployee Manager { 
     get { return base.Manager; } 
    } 
} 

주의를 작성할 수 그러나

(elmo.Manager as Employee).Manager = new Manager(); 

방지하기 위해 컴파일 할 때 당신이 아무 것도 없다.

5

아니요 - Liskov's Subsitution Principle이 깨질 수 있습니다. 기본적으로, 당신은 물건을 추가 할 수 있습니다, 그러나 당신은 그들을 빼앗아 갈 수 없습니다.

잠재적으로 런타임에 예외를 throw하도록 속성을 무시할 수는 있지만 컴파일 할 때 수행 할 수는 없습니다.

일반적으로 이러한 종류의 것을 허용하지 않으려면 정품 상속 관계가 없기 때문에 상속보다는 구성을 고려해야합니다.

0

다른 사람들이 말했듯이. 모든 직원에게 관리자와 조수가있는 것이 아니라면 상속 계층이 잘못되었다고 덧붙일 것입니다. 직원과 관리자가 공유하는 유일한 이름 인 것 같습니다. 상속을 통해 추가 할 수는 있지만 상속을 통해 가져갈 수는 없습니다.

0

아니요, 관리자가 직원이고 관리자와 보조자가 있거나 관리자가 아니기 때문에 다른 기본 클래스가 있어야합니다. 디자인 결함.한 가지 가능성은 도메인에 대해 의미가 있다고하더라도 이러한 속성에 대해 null을 반환하는 것일 수 있습니다.

1

대부분의 경우와 마찬가지로, 의존적입니다. 당신이 가상으로 선언되지 않은 속성을 재정의 할 수있는,

 bar a = new bar(); 
     // returns bar 
     literalTest1.Text = a.Test; 

     foo b = new foo(); 
     // returns "foo" 
     literalTest2.Text = b.Test; 

     foo c = new bar(); 
     // returns "foo" 
     literalTest3.Text = c.Test; 

당신은 볼 수 있습니다 위의 댓글 :

public class foo 
{ 
    public string Test { get { return "foo"; } } 
} 

public class bar : foo 
{ 
    public new string Test { get { return "bar"; } } 
} 

그리고 다음 코드를 다음과 같은 클래스 감안할 때. 그러나 재정의 된 속성은 개체 변수가 해당 조상을 오버라이드하는 형식으로 선언 된 경우에만 사용됩니다. 이것은 효과적으로 다형성을 파괴합니다.

대신 조상 클래스를 수정하십시오.