Re: Dynamic inheritance

From: Robert C. Martin (unclebob_at_objectmentor.com)
Date: 01/06/05


Date: Wed, 05 Jan 2005 17:19:20 -0600

On Mon, 3 Jan 2005 10:23:51 -0000, "James Harris" <no.email.please>
wrote:

>
>"Robert C. Martin" <unclebob@objectmentor.com> wrote in message
>news:p773s09rpcuidsid2f1rg86n6su7hojiv7@4ax.com...
>>
>>>I was thinking of (pseudocode)
>>> loop (from n=0) {
>>> read device_address (break if EOF)
>>> Device[n++] = create/new objClass (device_address)
>>> }
><snip>
>>
>> Your loop above could be accomplished using the "Abstract Factory"
>> pattern from the GOF book:
>>
>> DeviceFactory factory = ... // get factory from somewhere.
>> // usually created by main.
>> int n=0;
>> Device dev[NDEVICES];
>> while ((int addr = read()) != EOF){
>> dev[n++] = factory.make(addr);
>> }
>>
>> interface DeviceFactory {
>> Device make(int addr); // abstract method.
>> }
>
>I've been reading the Factory and Abstract Factory patterns - and finding
>it hard work! It seems the problem boils down to where/when to instantiate
>an object with the 'new' keyword. Even if this is wrapped in a function -
>as in 'make' in the example above - my code still needs to be fully aware
>of the object's type (at least in terms of the class hierarchy) at the
>point the object is instantiated.
>
>I think this still requires the correct subclass to be identified at
>instantiation time - albeit encapsulated in a function. This is basically
>the original problem come back again in a different place. I'm obviously
>missing something.

Yes. The factory does not have to be created at the same time, nor in
the same place, as the object you want to create. The factory can be
created by main and placed in a global variable.

Now consider. We have an interface named DeviceFactory. This
interface is implemented by a class named DeviceFactoryImp.

class MainClass {
  public static DeviceFactory factory = new DeviceFactoryImp();
  ...
}

Now your code can use MainClass.factory.make(some address). Your code
has no direct dependence upon DeviceFactoryImp. And DeviceFactoryImp
is the *only* class that knows how to map addresses into devices and
how to create those devices. The code that calls 'make' never needs
to depend on any of the derived devices.

>I've come back to this again because I have another requirement similar to
>the last one. This one is maybe more easily described. I want to collect
>information about a number of network devices. The sequence to get this
>info from the devices is something like
>
>1) telnet to and log in to the device
>2) collect basic information about the device - serial numbers, operating
>system version etc.
>3) depending on the type of operating system collect other basic
>information - uptime, configured name, detailed operating system version,
>boot parameters etc
>4) depending on the details obtained in the previous step collect
>information about the device's interfaces, SNMP settings, internal tables
>etc.
>
>I had thought of constructing a hierarchy of classes to define the commands
>etc such as (simplified)
>
>device
>device -> non-responding address
>device -> non-cisco device
>device -> cisco device
>device -> cisco device -> IOS operating system
>device -> cisco device -> IOS operating system -> router
>device -> cisco device -> IOS operating system -> switch
>device -> cisco device -> IOS operating system -> router/switch
>device -> cisco device -> CatOS operating system -> switch
>
>Class 'device' would deal with the IP address, DNS names and password.
>Since most devices would be Cisco devices the 'cisco device' subclass would
>have the few commands that work on all Cisco devices. Since most of the
>Cisco device types would run IOS they the IOS subclass would supply the
>basic IOS commands and then the subclasses thereof would supply the
>specifics required for particular device types.
>
>The trouble is, I won't know which subclass to finally instantiate until
>after collecting information about the device. As more information becomes
>available I could delete the previous instance and replace it with a more
>specific one but that means copying or losing the information already
>collected.

I wouldn't do that, it's not really that useful.
>
>I know I could gather all the relevant info first and then, in a large
>selection statement, instantiate the correct subclass but that requires
>knowledge of the devices to exist outside the class system and somewhat
>defeats the object of using OOP.

No, it doesn't defeat the purpose of OOP. It just doesn't jive with
your hopes for OOP. There really isn't any way to avoid the big
selection statement. Oh, you can break it up into a bunch of little
selection statements and scatter them into a hierarchy; but in the end
it's still a big selection.

However, once that selection is made, it never has to be made for that
instance again. Every further use of the device can be done in a
manner that is independent of the final knowledge of that device's
type.

>I believe I can only inherit from classes. If I could inherit from other
>instances (methods /and/ values) that would do the trick - but I don't
>think OOP will let me do that....

Some language let you do that. Most don't. However, you can simulate
it by creating a composition hierarchy instead of an inheritance
hierarchy.

-----
Robert C. Martin (Uncle Bob) | email: unclebob@objectmentor.com
Object Mentor Inc. | blog: www.butunclebob.com
The Agile Transition Experts | web: www.objectmentor.com
800-338-6716

"The aim of science is not to open the door to infinite wisdom,
 but to set a limit to infinite error."
    -- Bertolt Brecht, Life of Galileo



Relevant Pages

  • Re: Dynamic inheritance
    ... >I've been reading the Factory and Abstract Factory patterns - and finding ... It seems the problem boils down to where/when to instantiate ... We have an interface named DeviceFactory. ... >Since most devices would be Cisco devices the 'cisco device' subclass would ...
    (comp.object)
  • Re: ArrayList called with specific object constructors
    ... Still viewed Robert code but it can't work because instantiating an ... You don't instantiate interfaces. ... public interface Factory{ ...  Instead of 'new Factory ' try something like Robert Klemme's ...
    (comp.lang.java.programmer)
  • Re: ArrayList called with specific object constructors
    ... Still viewed Robert code but it can't work because instantiating an ... You don't instantiate interfaces. ... public interface Factory{ ...  Instead of 'new Factory ' try something like Robert Klemme's ...
    (comp.lang.java.programmer)
  • Re: ArrayList called with specific object constructors
    ... Still viewed Robert code but it can't work because instantiating an ... You don't instantiate interfaces. ... public interface Factory{ ...  Instead of 'new Factory ' try something like Robert Klemme's ...
    (comp.lang.java.programmer)
  • Re: =?UTF-8?B?SEVMUDrjgIBBIGNsYXNzIGhpZXJhcmNoeSBjb252ZXJ0IHRvL2Y=?= =?UTF-8?B?cm9tIGRpZmZyZ
    ... So I would expect the format to be the same for each Mx. ... Now all one needs to do is instantiate R2 to the proper subclass object for the desired Mx. ... The getValN interface will be implemented properly for each subclass to extract the data from the format in hand. ...
    (comp.object)