3

次のクラスは、ASP.NETアプリケーションで使用され、データベースの結果セットから通貨を読み取り、それらを合計します(たとえば、米ドルで合計を表示し、GBポンドで合計を表示します)。これは次のように機能します。

  1. 通貨ID値を読み取る
  2. 通貨IDがすでに存在する場合は、その通貨の合計を増やします
  3. 通貨IDが存在しない場合は、その値とともにリストに追加します

CurrencyIDこれは、プロパティを各固有の通貨間の差別化要因として使用するとうまく機能します。IsoCurrencySymbolただし、デフォルトでは通貨ごとに一意であることが明らかになったため、CurrencyID実際には必要ありません。

だから...このクラスから継承してへの参照を削除することが可能かどうか疑問に思っていたCurrencyIDので、代わりにCompareToメソッドを使用IsoCurrencySymbolします。

秘訣は、既存のクラスを広く使用されているままにして、変更されたバージョンを必要とせずCurrencyIDに導入することです。これは可能ですか?

<Serializable()> _
Public Class CurrencyCounter

    <Serializable()> _
    Private Class CurrencyType
        Implements IComparable

        Public IsoCurrencySymbol As String
        Public CurrencySymbol As String
        Public CurrencyID As Int16
        Public Amount As Decimal

        Public Function CompareTo(obj As Object) As Integer Implements System.IComparable.CompareTo
            If Not TypeOf (obj) Is CurrencyType Then
                Throw New ArgumentException("Object is not a currency type")
            Else
                Dim c2 As CurrencyType = CType(obj, CurrencyType)
                Return Me.CurrencyID.CompareTo(c2.CurrencyID)
            End If
        End Function

    End Class

    Private _Currencies As List(Of CurrencyType)

    Public Sub New()
        _Currencies = New List(Of CurrencyType)
    End Sub

    Private Sub AddStructToList(CurrencyID As Integer, IsoCurrencySymbol As String, CurrencySymbol As String, Amount As Decimal)
        If IsoCurrencySymbol <> String.Empty AndAlso Amount > 0 Then
            Dim s As New CurrencyType
            s.CurrencyID = CurrencyID
            s.IsoCurrencySymbol = IsoCurrencySymbol
            s.CurrencySymbol = CurrencySymbol
            s.Amount = Amount
            _Currencies.Add(s)
        End If
    End Sub

    Public Sub Add(CurrencyID As Integer, IsoCurrencySymbol As String, CurrencySymbol As String, Amount As Decimal)
        Dim ct As CurrencyType = _Currencies.Find(Function(obj) obj.CurrencyID = CurrencyID)
        If ct IsNot Nothing Then
            ct.Amount += Amount
        Else
            AddStructToList(CurrencyID, IsoCurrencySymbol, CurrencySymbol, Amount)
        End If
    End Sub

    Public Sub Clear()
        _Currencies.Clear()
    End Sub

    Public Function Count() As Integer
        Return _Currencies.Count
    End Function

    Public Function RenderTotals() As String
        ' ...
    End Function

End Class
4

1 に答える 1

4

いいえ、それはできません。継承の全体的なポイントは、すべての派生クラスが、少なくとも基本クラスと同じパブリック インターフェイスを共有することを保証することです。プロパティを削除すると、同じインターフェイスを共有しないため、互換性がなくなり、継承の候補になりません。

派生クラスが基本クラスの型であると言えない場合は、継承を使用できません。たとえば、自動車は乗り物の一種であると言えます。したがって、自動車クラスがあれば、それを自動車クラスから継承させることができます。しかし、昆虫が一種の乗り物であるとは言えません。したがって、共通点が多いとしても、乗り物クラスを昆虫クラスに継承させることはできません。

この制限の理由は、継承により、オブジェクトを基本型であるかのように扱うことができるためです (型キャストを介して)。例えば:

Public Sub AddPassengerToVehicle(v As Vehicle)
    v.Passengers.Add(New Passenger())
End Sub

' ...

Dim auto As New Automobile()
Dim bug As New Insect()
AddPassengerToVehicle(auto) ' Works because an automobile is a type vehicle (inherits from vehicle)
AddPassengerToVehicle(bug) ' Can't possibly work (nor should it)

そのため、基本クラスのメンバーの 1 つを削除/非表示にする派生クラスが必要な状況にある場合は、間違った方向に向かっています。そのような場合、たまたま非常によく似たインターフェースを持つまったく新しいクラスを作成する必要がありますが、最初のクラスとは直接的な関係はありません。たとえば、次のようになります。

Public Class Vehicle
    Public Property Passengers As List(Of Passenger)
    Public Property MaxSpeed As Integer

    Public Function SpeedIsTooFast(speed) As Boolean
        Return (speed > MaxSpeed)
    End Function
End Class

Public Class Insect
    Public Property MaxSpeed As Integer

    Public Function SpeedIsTooFast(speed) As Boolean
        Return (speed > MaxSpeed)
    End Function
End Class

上記の例のメソッドのロジックなどの機能を共有したい場合SpeedIsTooFastは、いくつかの方法があります。これは最初に、他のクラスへの呼び出しを行うだけのラッパーメソッドを作成することです。たとえば、次のようになります。

Public Class Insect
    Private _vehicle As New Vehicle()

    Public Property MaxSpeed() As Integer
        Get
            Return _vehicle.MaxSpeed
        End Get
        Set(value As Integer)
            _vehicle.MaxSpeed = value
        End Set
    End Property

    Public Function SpeedIsTooFast(speed) As Boolean
        Return _vehicle.SpeedIsTooFast(speed)
    End Function
End Class

このようにする場合は、両方のクラスに同じ共通インターフェースを実装して、必要に応じて交換可能に使用できるようにすることをお勧めします。次に例を示します。

Public Interface ISelfPoweredMovingThing
    Property MaxSpeed As Integer
    Function SpeedIsTooFast(speed As Integer) As Boolean
End Interface

もう 1 つのオプションは、共通の機能を 3 番目のクラスに分割し、そのクラスを他の 2 つのベースとして使用することです。たとえば、次のようになります。

Public Class SelfPoweredMovingThing
    Public Property MaxSpeed As Integer

    Public Function SpeedIsTooFast(speed) As Boolean
        Return (speed > MaxSpeed)
    End Function
End Class

Public Class Vehicle
    Inherits SelfPoweredMovingThing

    Public Property Passengers As List(Of Passenger)
End Class

Public Class Insect
    Inherits SelfPoweredMovingThing

    ' Anything else specific only to insects...
End Class
于 2013-02-21T13:21:48.687 に答える