CodingYourLife
CodingYourLife

Reputation: 8626

Class Design C# Casting

Let's say I have a program to write text into a file (not really but that's easier to explain). I want a seperate class for each filetype like PdfType and WordType that inherit from a FileTypeMaster.

FileTypeMaster (base)
-PdfType : FileTypeMaster
-WordType : FileTypeMaster (same methods as pdftype but works different)

Now to the real problem... I want the user to decide on programstart what type to use. If he wants Pdf OR Word the methodcall should look the same (because word is new and the program was just for pdf before).

How it should work for example with pdf:

static FileTypeMaster MyFavoriteType; //declare a general var 
MyFavoriteType = new PdfType(); //cast general var to the wanted type
MyFavoriteType.CompileThis();

How it should work with word: the same but MyFavoriteType = new WordType();`

Upvotes: 0

Views: 142

Answers (5)

phoog
phoog

Reputation: 43066

Your base type can be either a class or an interface. Let's say it's an interface:

interface IFileProcessor { void CompileThis(); }
class PdfProcessor : IFileProcessor { public void CompileThis() { /* ... implementation omitted ... */ }
class WordProcessor : IFileProcessor { public void CompileThis() { /* ... implementation omitted ... */ }

Then:

private enum ProcessorType
{
    Undefined,
    Word,
    Pdf
}

public void Main(string[] args)
{
    ValidateArgs(args); // implementation omitted
    ProcessorType requestedProcessor = GetRequestedProcessorFromArgs(args); // implementation omitted
    IFileProcessor processor = GetProcessor(requestedProcessor);
    processor.CompileThis();
}

private IFileProcessor GetProcessor(ProcessorType requestedProcessorType)
{
    switch (requestedProcessorType)
    {
        case ProcessorType.Pdf:
            return new PdfProcessor();
        case ProcessorType.Word:
            return new WordProcessor();
        default:
            throw new ArgumentException("requestedProcessorType");
    }
}

Upvotes: 0

Trevor Pilley
Trevor Pilley

Reputation: 16423

Only use a base class if you are sharing behaviour between your subclasses. If you are only sharing the method signatures and properties (e.g. each subclass doesn't really use any base class functionality) then use an interface instead.

Upvotes: 1

user1241335
user1241335

Reputation:

Interfaces are made for that. MyFavoriteType should be an interface, with anything you will ever need (functions and proprieties) built in. Then each wanted type will implement that interface and do their own thing.

Here is a small example:

public interface Polygon
{
  float GetArea();
}
public class Square : Polygon
{
  float Side;
  public Square(float side)
  {
    Side = side;
  }
  Polygon.GetArea()
  {
    return side*side;
  } 
}

You can now do something like so:

Polygon MyPolygon = new Square(5f);
float area = MyPolygon.GetArea();

And this will work for ANY SINGLE CLASS that correctly implements Polygon interface. So this is possible:

Polygon MyPolygon = new Circle(5f);
float area = MyPolygon.GetArea();

In your case, the interface would look like so:

public interface MyFavoriteType//or name it FileTypeMaster, since that's what you want to anme it
{
  void CompileThis();
}

Upvotes: 4

That Chuck Guy
That Chuck Guy

Reputation: 463

To add to the other posts, you then generally have a factory that given an indicator (like an enum value that represents the file type chosen by the user) generates an instance of the appropriate class and returns it as the interface type.

Upvotes: 0

Frederik Gheysels
Frederik Gheysels

Reputation: 56974

What you want to do here, is make use of polymorphism. Actually, you're kind off implementing the strategy design pattern here, where you have a base class (or interface)

public abstract class FileTypeMaster
{
    public abstract CompileThis();
}

And have different implementations, for Word and Pdf:

public class PdfType : FileTypeMaster
{
    public override CompileThis () {}
}

Then, in your calling program, you can create the correct implementation:

FileTypeMaster x = new PdfType();
x.CompileThis()

or

FileTypeMaster x = new WordType() x.CompileThis()

In fact, you can abstract the initialization away by using a factory class or a factory method:

public abstract class FileTypeMaster
{
    public abstract CompileThis();

    public static FileTypeMaster Create( FileType type )
    {
         switch( type )
         {
             case FileType.Word : return new WordType();

             case FileType.Pdf : return new PdfType();

             default:
                 throw new NotImplementedException();
         }
    }
}

Upvotes: 0

Related Questions