OO Pattern: Collaboration between Abstract Base Class and Subclasses

I have an abstract base class T from which classes A and B are inherited. Now I have an operation (on T ) that requires a slightly different implementation in A and B , but most of the code is the same. Let me give you an example: There are two possibilities to implement something like the .Clone method:

 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 

or

 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 

(an example is provided in VB.NET, but the same question applies to C #, Java, etc.)

My questions:

  • Is there an option that is clearly preferable?
  • Is this a well-known template that has a name (so that I can do more research)?
  • Are there well-established naming conventions for such situations (i.e. for the _Do... object)?
+4
source share
4 answers

If cloning requires code in the base class, the first option is correct. The second option allows you to implement the Clone method without calling the code in the base class.

If code in the base class is not required, the second option is correct. The first option does not allow you to implement the Clone method without calling the code in the base class.

+2
source

Similar to Method Template :

The template method is used to:

  • Let subclasses implement (through method overrides) behavior that can change
  • avoid code duplication: you are looking for generic code in the algorithm and implement options in subclasses
  • control at what point (s) subclasses are allowed.
+7
source

In general, I would use the first approach, since it is simpler. However, in some cases a second is required.

Please note that using cloning objects as an example may not be optimal. Cloning is special in that the returned object must be of the same type as the cloned object, although the overridden method is of the base type.

So, suppose you have a class B that inherits from A, and you do this:

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

Using the first approach, the cloned object must be created by A, but the type must be of type B. Usually you use object.MemberwiseClone() for this, but this prevents you from replacing readonly fields, since this can only be done in the constructor (for example, cloning a list, which should not be shared between the clone and the source object).

+1
source

The first option is fair enough when there is a certain work, which, as you know, will be different for derived classes. Perhaps you want to have

 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 

The second approach would be more appropriate if you just want to clone any old T, but want to make minor adjustments to subclasses. But in this case, override the Clone method, and do not create a new one with a new name. for instance

 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 

And no, that doesn't make much sense for the clone when you look at it, because you are going to get T back from the base clone, and converting this to is not that easy.

There are several other options that you might consider.

One of them is a helper class. Instead of having any code in T, you may need to move your generic code to a static method of a static class to avoid duplication.

The other has an ICloner interface, which T understands the contract, but A and B understand the implementation, for example

 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 

Confused enough?

+1
source

Source: https://habr.com/ru/post/1302464/


All Articles