Link to home
Start Free TrialLog in
Avatar of MyAsylum
MyAsylum

asked on

C# OOD Abstraction Principles

Hi there guys,
This will surely sound a bit elementary to the experienced programmer, but I feel I have missed an important concept of Inheritance (particularly abstraction).

The question is simple really:

I have a base class: "Request"
It contains several properties and methods which can be overridden.

Then I have a few derived classes, for example: "LookupRequest"
This classes inherits from Request, and overrides a couple properties/methods as stated above.

However, when creating an instance of LookupRequest using Polymorphism, I've ran into a problem. By typing something like:

Request request = new LookupRequest();

It works, however, I don't have access to any of the LookupRequest properties/methods. Just the base class (Request).

If I create an instance by implicitly typing:
var request = new LookupRequest();

Then I get access to the derived properties / methods as desired.
This seems like I'm missing an important concept to abstraction or polymorphism. Since you abstract classes are not meant and cannot by created instances, how does one properly invoke an inherited class?

Much thanks in advance!

-Danny
Avatar of MyAsylum
MyAsylum

ASKER

Hmm...
After doing a little digging, it seems the proper way to instantiate a derived class is to use the format:

DerivedClass class = new DerivedClass();

I guess I had gotten a bit confused while reading Head First - Design Patterns. In the book they illustrate a sample of polymorphism like so:

Duck mallard = new MallardDuck();
mallard.performQuack();

This code and the book's code is in Java though. So myself, (not being a java guru), I'm assuming Java's syntax uses polymorphism a little differently.
So now I'm curious how would one use C#'s method of polymorphism in a situation like this.
I have a design pattern Factory class which returns an instance of a created class ... see code snippet:

So this doesn't work because it returns an instance of the base class for some weird! reason.
Not only that, but I can't convert awsRequest to an implicit variable or else I'd have to initialize it right away, and I don't yet know which derived class to use.

internal AwsRequest GetOperation(Aws.AwsRequestOperation operation)
{
            AwsRequest awsRequest = null;
 
            switch(operation)
            {
                case Aws.AwsRequestOperation.BrowseNodeLookup:
                    awsRequest = new AwsBrowseNodeLookup();
                    break;
                case Aws.AwsRequestOperation.CartAdd:
                    awsRequest = new AwsCartAdd();
                    break;
                case Aws.AwsRequestOperation.CartClear:
                    awsRequest = new AwsCartClear();
                    break;
           }
 
           return awsRequest;
}

Open in new window

ASKER CERTIFIED SOLUTION
Avatar of Gautham Janardhan
Gautham Janardhan

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
That wouldn't work as I'm returning a generic AwsRequest class. Therefore I don't know what derived class I should cast too.
I've found some information on other .net design principles and techniques called early and late binding.
Late binding maybe what I'm looking for, however, I believe it makes use of Reflection.

I originally thought of using something like that, but doesn't all Reflection cause unwanted overhead on the program.
no if the type is a know type there is no need of reflection .. it's memory hungry and u dont want to go there if it can be avoided. but the concept of a factory calss fits mre into a situation where the child classes only overide functions that are there in the parent and dont need any of their own (they may need more for the internal processing but only the parent functionality is exposed ) and each wud do a job in a way of their own.
for example take an abstract class Animal with abstract methods move, breathe and blah blah blah each animal when implemted from this main class Animal would implement this in its own way.
That's interesting. My child classes override the abstract methods / properties, however they also have new properties which I need access to.

Is this not proper use of abstraction?
Should inherited classes only contain prop/methods from the base class?
that wud depend on ur requirement. but if u have extra functions and properties in ur child class then using the factory pattern would cause problems as u found out
For certain,
It looks like this is a known issue though. I'm not 100% sure this is what I need yet, but I'm reading it over.

Creating Dynamic Factories in .NET Using Reflection
http://msdn.microsoft.com/en-us/magazine/cc164170.aspx
I would much rather not use Reflection though. This class library will be used in a web environment so I'd like as much efficiency as possible. I'm going to try and re-think my approach.

Thanks for your help gauthampj.
Just want to update for future developers who may stumble upon this topic: this article illustrates a solution for creating dynamic polymorphism via Factory pattern.

Creating Dynamic Factories in .NET Using Reflection
http://msdn.microsoft.com/en-us/magazine/cc164170.aspx

I'm still unsure if I'm going to use this as Reflection is much undesired.
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Hi Kaufmed,
Let me provide a little more code so you can see the whole picture. You're solution would work, however, the method which calls the factory method does not know which derived class it will be returning; therefore a cast would not be possible.

See attached code:

The AwsRequest class contains properties and methods that are common to all it's derived classes. However, each derived class has unique properties and methods which need to be accessible like you illustrated in your last post.

Unfortunately, the only way I could apply a cast would be to use another switch or if statement within the method calling the factory. It would look like:

public AwsRequest CreateRequest(AwsRequestOperation operation)
{
            var awsFactory = new AwsFactory();
            if(operation == AwsRequestOperation.BrowseNodeLookup)
                 return (AwsBrowseNodeLookup)awsFactory.GetOperation(operation);
            else if.....
}
public AwsRequest CreateRequest(AwsRequestOperation operation)
{
            var awsFactory = new AwsFactory();
            return awsFactory.GetOperation(operation);
}
 
-----------------------------------------------------------------------
 
internal sealed class AwsFactory
{
        internal AwsRequest GetOperation(Aws.AwsRequestOperation operation)
        {
            switch(operation)
            {
                case Aws.AwsRequestOperation.BrowseNodeLookup:
                    return new AwsBrowseNodeLookup();
                case Aws.AwsRequestOperation.CartAdd:
                    return new AwsCartAdd();
                case Aws.AwsRequestOperation.CartClear:
                    return new AwsCartClear();
            }
        }
}

Open in new window

I'm surprised that there's not much information on a dynamic factory pattern. Since that is one of the most common. Unless inherited classes are really only meant to contain overridden prop/methods, this leaves a major gap in what the factory can do.

I'm really trying to avoid Reflection.
If anyone would like, I can provide the entire project for download. It's very small as I just started a day or so ago. It's a .NET 3.5 library for Amazons Web Services. It will be released open source for developers to contribute and expand it's functionality.
I'm going about this the wrong way.
Even if it could return the correct derivedType, the programmer wouldn't be able to use the derived class's unique methods or properties since that would only be known at runtime.
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Sorry about the delayed response. I've modified the architecture a bit so this is no longer a problem. I really just wasn't thinking too clearly before and it doesn't help what you jump into programming before any significant planning or diagramming.

Thanks ppittle for your response. I'm using abstraction because the base class contains several overridden properties/methods for the child classes.

I've bumped up the points and will divide them out. :) Thanks again for all your input.
can u say how u modified ur soln ? just curious :-)