views:

462

answers:

1

I haven't actually done this yet, and maybe I don't need to, but it made sense to me. I have a baseclass, say BaseClass, where I have several derived classes, say Derived1,Derived2,Derived3. I have several operations that apply only to one particular function, namely generating a PDF. My idea was take all of those methods (some are abstract from the baseclass) and plug them into a nested abstract class within the Base Class, like this:

Public MustInherit Class BaseClass
    Protected MustOverride Sub MethodA()
    Protected MustOverride Sub MethodB()

    ...stuff

    Protected MustInherit Class PDFOperations
        Protected MustOverride Sub Method1()
        Protected MustOverride Sub Method2()

        etc.

    End Class
End Class

This way when I want to find something in my class, I can abstract my PDF operations from everything else, which will keep my interface way cleaner. Is there any way to do this so that my derived classes will be forced to override the nested class and all of its methods? Or is this just a silly way to go about doing this?

+1  A: 

Your line of thinking is understandable, you just need to take it one step further.

Public MustInherit Class BaseClass
    Protected MustOverride Sub MethodA()
    Protected MustOverride Sub MethodB()

    ...stuff

    Protected MustInherit Class PDFOperations
        Protected MustOverride Sub Method1()
        Protected MustOverride Sub Method2()

        etc.

    End Class

    Protected MustOverride ReadOnly Property PDF
End Class

Simply making the nested class abstract isn't enough to require that the inherited class actually implement them (as you don't actually reference that class anywhere). .NET nested classes are similar to nested static classes in Java, in that they have no reference to a specific instance of the containing class, they're simply grouped, for lack of a better term, by the outer class and have access to the private, protected, and internal members of the containing class.

By providing an abstract readonly property that is of the abstract inner class's type, you then require that the inheriting class provide SOME concrete implementation of it and should break up your methods just as you like.

Edit

While it isn't possible to absolutely enforce that EVERY class that inherits from BaseClass provide a distinct implementation of the PDFOperations class, this is enforced from a practical perspective because any class that inherits from PDFOperations will have to be a Protected nested class of the class that inherits from BaseClass. This means that they cannot share implementations.

Examples

Public Class DerivedOne Inherits BaseClass
    Protected Overrides Sub MethodA() ...
    Protected Overrides Sub MethodB() ...

    Private pdfInstance as PDFOne

    Protected Class PDFOne Inherits PDFOperations
        Protected Overrides Sub Method1() ...
        Protected Overrides Sub Method2() ...

        Private instance as DerivedOne

        Public Sub New(ByVal instance as DerivedOne)
            Me.instance = instance
        End Sub
    End Class

    Protected Overrides ReadOnly Property PDF
        Get
            If pdfInstance is Nothing Then pdfInstance = new PDFOne(Me)

            return pdfInstance
        End Get
    End Property
End Class

Public Class DerivedTwo Inherits BaseClass
    Protected Overrides Sub MethodA() ...
    Protected Overrides Sub MethodB() ...

    Private pdfInstance as PDFTwo

    Protected Class PDFTwo Inherits PDFOperations
        Protected Overrides Sub Method1() ...
        Protected Overrides Sub Method2() ...

        Private instance as DerivedTwo

        Public Sub New(ByVal instance as DerivedTwo)
            Me.instance = instance
        End Sub
    End Class

    Protected Overrides ReadOnly Property PDF
        Get
            If pdfInstance is Nothing Then pdfInstance = new PDFTwo(Me)

            return pdfInstance
        End Get
    End Property
End Class

In PDFOne and PDFTwo, there is an instance variable called instance that represents a reference to the containing object that inherits from BaseClass

Adam Robinson
how do i make it so each derived class has to override the abstract methods in the abstract readonly property?
Jason
See my edit, that may make more sense to you.
Adam Robinson
i think i may have worded this wrong... what i want is the same expected functionality across derived objects, but just pulled out and separated so that i can do something like `someDerivedObj.PDF.DoSomething()` and be able to override that functionality in each different derived class...
Jason
RE: your edit - i'm not really looking to inherit from the PDF class... i think that's where i'm going astray. i just want it to provide a bunch of method sigs that have to be overridden...
Jason
No, I understand what you want. Taking this approach will accomplish that. It's just slightly more verbose because each class that inherits from BaseClass will have to declare a protected nested class that inherits from PDFOperations and implements those functions, then return an instance of that nested class to the abstract PDF property.
Adam Robinson
can you think of a better way to do this? it seems overly complex, and obviously the idea is to reduce complexity.
Jason
Just to clarify, the functionality is the same from an external API perspective. What you want to do--essentially providing a "grouping" of methods--isn't strictly possible. Again, the desired result can be accomplished from what I've outlined, but what you are SPECIFICALLY asking for can't.
Adam Robinson
It's really not that complex. I will post an example.
Adam Robinson
ok, that's probably what i needed to hear. thanks :)
Jason
I've posted an example. See if this is clearer. Yes, it is *slightly* more complex than what you proposed, but it has the advantage of being, you know, possible ;)
Adam Robinson
mmm ok i see... not bad. possible is good :) thank you so much!
Jason
if you're still around, i have one last question: how do you acess the members of the containing object? for instance, if i am in the `PDFTwo` method, how do I get `SomeProperty` from `DerivedClass2`?
Jason
All you need is a reference to an instance of the class. I've updated the example with a typical pattern for how that's done.
Adam Robinson