2014-09-17 4 views
1

이 질문을 일반화하여 아직 의미가 있지만 실제로 실제 클래스의 코드가 모두 포함되지 않도록하려고 시도했습니다. 기본적으로 파생 클래스의 메서드가 조상 메서드 중 하나를 재정의하지만 조상 메서드의 시그니처의 매개 변수 인 클래스에서 파생 된 매개 변수를 사용하고 싶습니다. 희망이 코드를 더 잘 설명 : 나는 BaseVehicle의 모든 하위에 대한 SaveChanges를 방법의 코드를 반복하고 싶지 않아C# 상속은 하위 클래스가있는 메서드 매개 변수를 재정의합니다.

public abstract class BaseShape 
{ 
    public int Id { get; set; } 
    public bool Active { get; set; } 

    public abstract bool Modified(); 

    public abstract void Validate(List<string> errors); 
} 

public class DescendantShape : BaseShape 
{ 
    public int AnotherProperty { get; set; } 

    public override bool Modified() 
    { 
     return true; 
    } 

    public override void Validate(List<string> errors) 
    { 
     // 
    } 
} 

public abstract class BaseVehicle 
{ 
    public void SaveChanges(BaseShape shape) 
    { 
     if (!shape.Modified()) return; 
     var errorList = new List<string>(); 
     shape.Validate(errorList); 
     if (errorList.Count > 0) 
     { 
      var sb = new StringBuilder(); 
      foreach (string s in errorList) 
      { 
       sb.Append(s + Environment.NewLine); 
      } 
      throw new Exception(sb.ToString()); 
     } 

     WriteToStorage(shape); 

     if (!shape.Active) 
      MarkInactive(ref shape); 
    } 

    public abstract void WriteToStorage(BaseShape shape); 

    public abstract void MarkInactive(ref BaseShape shape); 
} 

public class DescendantVehicle : BaseVehicle 
{ 
    public override void WriteToStorage(DescendantShape shape) 
    { 
     // 
    } 

    public override void MarkInactive(ref DescendantShape shape) 
    { 
     shape = null; 
    } 
} 

; 그러나 BaseVehicle의 모든 자손은 Baseeshape의 다른 자손을 사용할 것입니다. 위의 코드는 물론 빌드되지 않으며 내가 왜 (또는 적어도 내가 생각한다고) 이해하는 동안, 나는 그것을 올바르게 디자인하는 방법을 찾기 위해 매일 아침 내 머리를 긁적 거렸다.

+0

이 코드를 컴파일 할 때 어떤 오류가 발생합니까? –

+0

C#이 (가) 없습니다. 무엇을 찾고 계십니까? [contravariant method arguments] (http://en.wikipedia.org/wiki/Covariance_and_contravariance_%28computer_science%29#Contravariant_method_argument_type). 아마도 어쩌면 에릭 리 퍼트 (Eric Lippert)에 의해 그것에 대해 대답 할 것입니다. –

+1

'새로운 DescendantVehicle.WriteToStorage (new SomeOtherShape()) '를 호출하면 어떻게 될 것으로 예상됩니까? 기본적으로 C#은 달성하고자하는 것을 직접 지원하지는 않지만 제네릭 사용을 고려할 수도 있습니다. –

답변

1

당신은 그래서 당신의 차량 클래스를 업데이트하여 당신이 후에 어떤 수행 할 수 있습니다 :

public abstract class BaseVehicle<T> where T : BaseShape 
{ 
    public void SaveChanges(T shape) 
    { 
     if (!shape.Modified()) return; 
     var errorList = new List<string>(); 
     shape.Validate(errorList); 
     if (errorList.Count > 0) 
     { 
      var sb = new StringBuilder(); 
      foreach (string s in errorList) 
      { 
       sb.Append(s + Environment.NewLine); 
      } 
      throw new Exception(sb.ToString()); 
     } 

     WriteToStorage(shape); 

     if (!shape.Active) 
      MarkInactive(ref shape); 
    } 

    public abstract void WriteToStorage(T shape); 

    public abstract void MarkInactive(ref T shape); 
} 

public class DescendantVehicle : BaseVehicle<DescendantShape> 
{ 
    public override void WriteToStorage(DescendantShape shape) 
    { 
     // 
    } 

    public override void MarkInactive(ref DescendantShape shape) 
    { 
     shape = null; 
    } 
} 

이 존 소총으로 언급 한 바와 같이 generics를 구현하는 솔루션입니다.

+0

와우 빨리! 감사. –

관련 문제