2014-11-09 5 views
0

나는 기본 클래스 BaseSorterParser 클래스를 파생 시켰습니다. BaseResult과 동일한 것은 도출 된 SorterResultParserResult입니다. BaseBaseResult 유형의 Result 필드를 가지며 BaseResult 필드는 Log 필드를 갖습니다. Base 클래스를 사용한 이유는 ParserSorter 모두 로그를 작성해야하기 때문입니다. 변수 '결과'에 enter image description hereVB.NET 상속 문제

"변수 '결과'충돌 기본 클래스 '자료'

Public MustInherit Class Base 
    Public Result As BaseResult 
    Event LogChanged() 
    Protected Sub AddLogLine(ByVal _logString As String) 
     If Not String.IsNullOrWhiteSpace(_logString) Then Result.Log.Add(_logString) 
     RaiseEvent LogChanged() 
    End Sub 
End Class 

Public Class Sorter 
    Inherits Base 
    Public Shadows Result As SorterResult 
    Sub New() 
     Result = New SorterResult With {.Log = New List(Of String)} 
    End Sub 
    Sub Go() 
     AddLogLine("Sorter started") 
    End Sub 
End Class 

Public Class Parser 
    Inherits Base 
    Public Shadows Result As ParserResult 

    Sub New() 
     Result = New ParserResult With {.Log = New List(Of String)} 
    End Sub 
    Sub Go() 
     AddLogLine("Sorter started") 
    End Sub 
End Class 

Public MustInherit Class BaseResult 
    Public Log As List(Of String) 
End Class 

Public Class SorterResult 
    Inherits BaseResult 
    '//SorterResult fields 
End Class 

Public Class ParserResult 
    Inherits BaseResult 
    '//ParsedResult fields 
End Class 

여기서 문제는 (아래 그림)에 그 컴파일러 SAIS입니다 : 여기 내 코드입니다 'Shadows'라고 선언해야합니다. " 나는 그림자 키워드를 사용, 경고가 사라졌다,하지만 Result 필드 Nothing 때문에 나는이 라인에 null 참조 예외가 : 나는 Base 클래스 생성자에 Result 변수에 값을 할당 할 수 없습니다

If Not String.IsNullOrWhiteSpace(_logString) Then Result.Log.Add(_logString) 

왜냐하면 SorterSorterResult 유형이고 에 ParserResult 유형이어야하기 때문입니다. 규칙적인 패턴은 무엇입니까? 미안하지만 내 나쁜 영어.

enter image description here

+1

(http://msdn.microsoft.com : 어쩌면

당신도 하나의 글로벌 로거가 있어야합니다 /en-us/library/1h3wytf6.aspx) MyBase를 사용하여 지정할 수 있습니다. 하지만 당신의 접근 방식이 좋지 않다고 생각합니다. [이 링크] (http://msdn.microsoft.com/en-us/library/c4swkw24.aspx)는 '그림자'에 대해 자세히 설명합니다. – bansi

+0

@bansi, 더 나은 접근 방식을 제안 할 수 있습니까?내 모든 패턴이 틀렸어? – AsValeO

답변

2

사용 제네릭

Public MustInherit Class Base(Of TResult As BaseResult) 
    Public Result As TResult 

    Event LogChanged() 

    Protected Sub AddLogLine(ByVal _logString As String) 
     If Not String.IsNullOrEmpty(_logString) Then Result.Log.Add(_logString) 
     RaiseEvent LogChanged() 
    End Sub 

    Public MustOverride Sub Go() 
End Class 

Public Class Sorter 
    Inherits Base(Of SorterResult) 

    Sub New() 
     Result = New SorterResult With {.Log = New List(Of String)} 
    End Sub 

    Public Overrides Sub Go() 
     AddLogLine("Sorter started") 
    End Sub 
End Class 

Public Class Parser 
    Inherits Base(Of ParserResult) 

    Sub New() 
     Result = New ParserResult With {.Log = New List(Of String)} 
    End Sub 

    Public Overrides Sub Go() 
     AddLogLine("Sorter started") 
    End Sub 
End Class 

그러나, 이것은 "아름다운"상속 계층 구조가 아닙니다. 상속은 student이 파생 된 "학생은 사람"과 같은 관계를 공식화해야합니다. person. 소터와 파서는 공통점이 무엇입니까? 그들은 Base입니까? 그들은 로거입니까? 그들은 명령입니까 ( Go 방법을 제안)? 상속이 여기에 필요합니까? 집계를 사용하는 것이 더 적절하지 않습니까? 완전히 독립적 인 로거 클래스를 선언하고 클래스에 삽입합니다. 이를 통해 다양한 유형의 로거를 주입 할 수 있으므로 유연성이 향상됩니다.

Public MustInherit Class Logger 
    Public Event LogChanged() 

    Public MustOverride Sub AddLogLine(ByVal message As String) 

    Protected Sub OnLogChanged() 
     RaiseEvent LogChanged() 
    End Sub 
End Class 

Public Class TextFileLogger 
    Inherits Logger 

    Public Overrides Sub AddLogLine(ByVal message As String) 
     If Not String.IsNullOrEmpty(message) Then 
      'TODO: Write message to log file 
      OnLogChanged() 
     End If 
    End Sub 
End Class 

당신은 이런 식으로 주입 할 수 있습니다 :이 같은

Public Class SomeConsumerClass 
    Private _logger As Logger 

    Sub New(ByVal logger As Logger) 
     _logger = logger 
    End Sub 

    Public Sub DoSomething() 
     _logger.AddLogLine("Did something!") 
    End Sub 
End Class 

사용 :

Dim obj As New SomeConsumerClass(New TextFileLogger()) 
obj.DoSomething() 

당신이 로거의 또 다른 종류가있는 경우 (XmlFileLogger, StringListLogger, DatabaseLogger ...)를 이제 모든 클래스를 변경하지 않고도 쉽게 사용할 수 있습니다. 당신은 당신이 [그림자] 사용할 때`클래스 Base`에`Result`을 할당하지 않는

Dim globalLogger As New TextFileLogger() 
Dim sorter As New Sorter(globalLogger) 
Dim parser As New Parser(globalLogger) 
+0

고마워요, 올리버, 오늘 뭔가 새로운 것을 배웠습니다. 이제 로깅이 작동합니다. 유일한 문제는'Sorter' 메소드에서'SorterResult'의 다른 필드를 볼 수 없다는 것입니다 (예를 들어). 컴파일러는 여전히'BaseResult' 타입의'Result'를 봅니다. 유일한 방법은'SorterResult' 타입의 변수를 정의하고, 그것으로 작업 한 다음, 그 값을'Result'에 할당하는 것입니다. 전체 패턴에 대해 어떻게 생각하세요? 어쩌면 내가 복잡한 일을 할 수 있을까? 제 아이디어는'Result'가'Log'를 포함하여 파생 된 클래스에 대한 모든 정보를 가지고 있다는 것입니다. – AsValeO

+1

'Sorter'에서'Base' ('SorterResult')를 상속 받았다고 선언하셨습니까? –

+0

내가 기대했던 것보다 많은 것을 얻었습니다. 이제는 생각할 것이 많습니다. 다시 한번 고마워, 올리버! 나는 그것을 고쳤다, 지금 모든 작품. 와우! – AsValeO