tags:

views:

55

answers:

5

hi i have two classes, example: ftp1 (handles normal ftp stuff), ftp2 (handles secure ftp connections, and stuff). based on a configuration setting I need to instantiate a type that can be one of these two types as a class level variable. Is this possible, if so, can someone point me in the right direction. I've tried to apply polymorphism to this situation, but I'm a little confused as to how to do that?

A: 

You can achieve this by using interfaces. With the following code you need to make the receiving method accept an instance of a class which implements iftp.

interface iftp {
  string address;
  int port;
  void SomeMethod();
}


class ftp1 : iftp {
  void SomeMethod() {
    /* implement regular ftp logic */
  }
}

class ftp2 : iftp {
  void SomeMethod() {
    /* implement secure ftp logic */
  }
}
Fabian
what if the two classes are part of a 3rd party framework and I don't have control over their implementation? basically, i just want to be able to do the following:public someclass{ private (polymorphedType) myVariable; private void somemethod() { if(something) { myVariable = new something(); } else { myvariable = new something2(); } }}
danielea
@danielea Intresting ... i would probably go for something like passing parameter of type object and try to figure out what type it is when i need it with typeof(classname) == parameter.GetType().
Fabian
I tried to do something similiar, i think, to what you are suggesting, but couldn't get it to work. can you give me an example?
danielea
A: 

Two options stick out to me and which to use changes depending on the situation:

  • BaseClass with InheritedClassess
    • If ftp1 and ftp2 share common functionality but extend that functionality in unique ways, you could use a base class with several implementing subclasses. This way, you can have other properties and methods in your program that expect the base class and have access to common properties.

.

public abstract class FtpBase {
    public string ConnectionInformation
    public int TimeoutSeconds
}

public class ftp1 : FtpBase {
    public void MakeConnectionToFTPServer() {...}
}

public class ftp2 : FtpBase {
    public void MakeSecureConnectionToFTPSever() {...}
}
  • Interfaces
    • Another option is to use interfaces, where you define what you expect the implementing classes to have. You can still tell other properties and methods to expect the interface as a parameter or property type; as long as the passed object implements the interface, it will be able to work. The consume code doesn't care what the object is as long as it implements the interface.

.

public interface IFtp {
    public void MakeConnection()
}

public class ftp1 : IFtp {
    public void MakeConnection (){...code to make a regular connection}
}

public class ftp2 : IFtp {
    public void MakeConnection (){...code to make a secure connection}
}

//Then you might have in some other code:

public void ConnectViaFtp(IFtp ftp) {
     ftp.MakeConnection()   // the code doesn't know if this is ftp1 or 
                            // ftp2. All it cares about is calling
                            // MakeConnection().
}

If both ftp classes are expected to have the same functionality with different implementations, I would use interfaces. However, if each ftp class shares only some of the same properties and methods (where the functionality of the methods in each implementation is the same) but extends common functionality uniquely between the two, you might use BaseClass with InheritedClasses. You can also use a combination of the two, depending on your situation.

Ben McCormack
A: 

Remember that interfaces define what something does, and implementation defines how it does it.

So, in your case, define an ftp interface that defined the actions you want - logging in, getting a file listing, putting a file getting a file, disconnecting etc.

The create two implementations, one for normal ftp, one for secure. You may find it useful to create a 'base' ftp implemtation with general processing that is extended by the two specific derivatives.

So you have:

ftp interface - containing method declarations for provided fuinctionality

baseftp abstract class - implementation of ftp interface, calling defined abstract methods for secure or non-secure specific actions

secureftp concrete class - implements abstract methods defined in baseftp for a secure connection

insecureftp concrete class - implements abstract methods defined in baseftp for a nonsecure connection

Visage
thanks visage, you are correct however what if the two classes are part of a 3rd party framework and I don't have control over their implementation? basically, i just want to be able to do the following: public someclass { private (polymorphedType) myVariable; private void somemethod() { if(something) { myVariable = new something(); } else { myvariable = new something2(); } } }
danielea
Then you should use composition and delegation. In your concrete class delegate method calls to an appropriate instance of the third party library
Visage
A: 

If the two FTP classes are part of a third-party framework (and do not already implement a common base class), you have two options:

Wrap the classes in a new class, which implements a common base class or interface

//Interface for original library classes.
public someClass {
    public void DoSomething();
}

public someClass2 {
    public void DoSomething();
}

//Wrapper implementation
public wrappedSomeClass : baseSomeClass {
    private someClass mSomeClass;

    public wrappedSomeClass() {
        mSomeClass = new someClass();
    }

    //DoSomething will need to be defined in baseSomeClass
    public overrides void DoSomething() {
        mSomeClass.DoSomething();
    }
}

public wrappedSomeClass2 : baseSomeClass {
    private someClass2 mSomeClass2;

    public wrappedSomeClass2() {
        mSomeClass2 = new someClass2();
    }

    //DoSomething will need to be defined in baseSomeClass
    public overrides void DoSomething() {
        mSomeClass2.DoSomething();
    }
}

Once the wrappers are written, you write your new code using the wrapper classes.

Store the values in a variable of type Object

The object data type is the common base for all classes. Your code would look like this:

public someclass {
    private object myVariable;
    private void somemethod() {
        if(something) {
            myVariable = new something();
        } else {
            myvariable = new something2();
        }
    }
}

When you use the value of the variable, you will almost always need to cast it back to its original type.

if(something) {
    ((something)myVariable).InvokeMethod();
} else {
    ((something2)myVariable).InvokeMethod();
}
AaronSieb
the second option definitely works, and is easiest to implement, but still ties me to knowing what type i am using instead of being able to just use myvariable.invokemethod();
danielea
@danielea Then option one is the way you'll want to go.
AaronSieb
A: 

Maybe you can implement a Factory Mehod Patther or a simple Strategy method one. PLase take a look at this code examples at

Factory Method Pattern

Strategy Pattern

Hope this helps you to achieve your goal.

regards

Juan Zamora M