代码之家  ›  专栏  ›  技术社区  ›  Heinzi

OO模式:抽象基类和子类之间的共享工作

  •  4
  • Heinzi  · 技术社区  · 15 年前

    我有一个抽象基类 T ,从哪个班 A B 继承。我现在有手术 T )这需要在 但大多数代码是相同的。让我举个例子:有两种可能实现类似 .Clone 方法:

    Public MustInherit Class T
        Protected MustInherit Function _DoClone() As T
    
        Public Function Clone() As T
            Dim clone = Me._DoClone()    ' do the subclass-specific stuff '
            ... ' do the shared stuff '
        End Function
    End Class
    
    Public Class A
        Inherits T
    
        Protected Overrides Function _DoClone() As T
            ... ' do the subclass-specific stuff '
        End Function
    End Class
    

    Public MustInherit Class T
        Protected Sub _DoClone(clone As T)
            ... ' do the shared stuff '
        End Function
    
        Public MustInherit Function Clone() As T
    End Class
    
    Public Class A
        Inherits T
    
        Public Overrides Function Clone() As T
            Dim clone = ... ' do the subclass-specific stuff '
            Me._DoClone(clone)
        End Function
    End Class
    

    (例子是在VB.NET,但是同样的问题适用于C、Java等)。

    我的问题:

    • 是否有明确首选的方案?
    • 这是一个有名字的著名模式吗(这样我可以做更多的研究)?
    • 对于这种情况(即 _Do... 什么事?
    4 回复  |  直到 15 年前
        1
  •  2
  •   Guffa    15 年前

    如果克隆工作需要基类中的代码,则第一个选项是正确的。第二个选项允许您实现克隆方法而不调用基类中的代码。

    如果不需要基类中的代码,则第二个选项是正确的。第一个选项不允许在不调用基类中的代码的情况下实现克隆方法。

        2
  •  7
  •   Anton Gogolev    15 年前

    看起来像 Template method 图案:

    模板方法用于:

    • 让子类实现(通过方法重写)可以改变的行为
    • 避免代码重复:在算法中查找通用代码,并在子类中实现变量
    • 控制允许在哪一点进行子类化。
        3
  •  1
  •   Lucero    15 年前

    一般来说,我会使用第一种方法,因为它比较简单。但是,在某些情况下需要第二个。

    请注意,以对象克隆为例可能不是最佳的。克隆是特殊的,因为返回的对象必须与要克隆的对象具有相同的类型,即使重写的方法是基类型。

    所以假设你有一个从A继承的B类,你这样做:

    A a = new B();
    B b = (B)a.Clone();
    

    使用第一种方法,克隆的对象必须由A创建,但类型必须是B类型。通常您将使用 object.MemberwiseClone() 要实现这一点,但这会阻止您替换只读字段,因为只能在构造函数中进行替换(例如,克隆一个不能由克隆和原始对象共享的列表)。

        4
  •  1
  •   pdr    15 年前

    第一种选择是足够公平的,当您知道某个特定的作业在不同的派生类中会有所不同。也许你想要

    Public MustInherit Class T
        Protected MustInherit Function Clone() As T
    
        Public Function CloneAdjusted() As T
            Dim clone = Me.DoClone()
            ' Adjust clone '
        End Function
    End Class
    
    Public Class A
        Inherits T
    
        Protected Overrides Function Clone() As T
            ' Make exact copy of A '
        End Function
    End Class
    

    如果您只是想克隆任何旧的T,但是想在子类中做一些小的调整,那么第二种方法就更合适了。但在本例中,请重写clone方法,而不是使用新名称创建新方法。例如

    Public MustInherit Class T
        Public Overridable Function Clone() As T
            Dim clone = ' Clone a T here '
        End Function
    End Class
    
    Public Class A
        Inherits T
    
        Public Overrides Function Clone() As T
            ' Any pre-clone work '
            T obj = MyBase.Clone()
            ' Any post-clone work '
        End Function
    End Class
    

    不,这对于一个克隆来说并不是完全有意义的,当你看它的时候,因为你要从基本克隆中得到一个T,把它转换成A并不是那么容易。

    还有一些其他的选择你可以考虑。

    一个是帮助类。您可能希望将公共代码移到静态类的静态方法中,以避免重复,而不是将任何代码移到T中。

    另一个是拥有一个ICloner接口,它不理解合同,但是A和B理解实现,例如

    Public MustInherit Class T
        Protected ICloner Cloner
    
        Public Overridable Function Clone() As T
            ' Common Code '
            Dim clone = Cloner.GetClone()
            ' More Common Code '
        End Function
    End Class
    
    Public Class A Inherits T
        Public Sub New()
            Cloner = New ACloner(Me)
        End Sub
    End Class
    

    足够困惑了吗?

    推荐文章