Tech Off Thread

13 posts

multiple variations of an abstract method?

Back to Forum: Tech Off
  • User profile image
    phreaks

    I would like an abstract method that has 2 different signatures. Is this possible in C#?

    I don't care which method is used in the derived class, as long as one of them is implemented.

    //Psuedo

    abstract class psuedoClass
    {
          
          public abstract void DoThingy(Thing thing1, Thing thing2);
          public abstract void DoThingy(Thing thing1);

    }

  • User profile image
    Dr Herbie

    phreaks wrote:
    I would like an abstract method that has 2 different signatures. Is this possible in C#?

    I don't care which method is used in the derived class, as long as one of them is implemented.

    //Psuedo

    abstract class psuedoClass
    {
          
          public abstract void DoThingy(Thing thing1, Thing thing2);
          public abstract void DoThingy(Thing thing1);

    }


    I think it should be possible as the full signature is used to define the method, but derived classes would have to implement both methods to fulfull the contract.

    Herbie.

  • User profile image
    phreaks

    Thanks Herbie, but what I am really looking for is a solution that only forces 1 implementation of the required method.

  • User profile image
    GuyIncognito

    I'm almost positive that you can't say "one or the other must be implemented in a derived class" in c#.  In fact, I'd like to know what languages that is possible in? 

    How would your base class decide which one to use? 

    I'm guessing an alternative design pattern might be a better solution.



    Could you go into a little more about your code?

  • User profile image
    phreaks

    GuyIncognito wrote:
    I'm almost positive that you can't say "one or the other must be implemented in a derived class" in c#.  In fact, I'd like to know what languages that is possible in? 

    How would your base class decide which one to use? 

    I'm guessing an alternative design pattern might be a better solution.



    Could you go into a little more about your code?


    I have concrete classes that needs either 1 or 2 date parameters to operate.

    They get their parameters from a custom Winform DateFrame Control. Which Could be DateFrame : DefaultFrame or DateRangeFrame : DefaultFrame

    I don't know until Runtime what DateFrame Control or Concrete 'Thingy' class needs to be instantiated.

    So Depending on Runtime conditions I
    a) Load up a Concrete DateFrame Control that has either 1 Date comboBox or 2 date ComboBoxes.
    b) Load up a 'Thingy' class that corresponds to the properDateFrame Control (1 date or 2)

    In my Base class, I currently have the method marked as virtual, but would like to 'force' a custom implementation in each derived class.

  • User profile image
    nlondon

    it is full of potential problems, but maybe this might work for you:

    abstract class psuedoClass
    {
          public abstract void DoThingy(Thing thing1, Thing thing2);
          public virtual void DoThingy(Thing thing1){
             DoThingy(thing1,null);
          }

    }

  • User profile image
    JohnAskew

    nlondon wrote:
    

    it is full of potential problems, but maybe this might work for you:

    abstract class psuedoClass
    {
          public abstract void DoThingy(Thing thing1, Thing thing2);
          public virtual void DoThingy(Thing thing1){
             DoThingy(thing1,null);
          }

    }




    The first potential problem I would imagine is that the virtual method has to make assumptions about the abstract method it calls.

    The second parameter needs to handle a null value, which is not explicitly noted for the inheriting class -- comment the method?

    I can't think of a second potential problem...

  • User profile image
    Sven Groot

    Maybe you could just implement them both and throw a NotImplementedException on the one you don't need? I do however think that you may want to consider an alternative design. I need to know more about the problem to make any suggestions though. Usually in the case where not all derived classes will be implementing the abstract method, I'd say it doesn't belong in the base class in the first place.

  • User profile image
    Dr Herbie

    How about

    abstract void Method(params Thingy[])

    Then in the derived class you can handle the case for multiple parameters?


    Herbie

  • User profile image
    phreaks

    Sven Groot wrote:
    Maybe you could just implement them both and throw a NotImplementedException on the one you don't need? I do however think that you may want to consider an alternative design. I need to know more about the problem to make any suggestions though. Usually in the case where not all derived classes will be implementing the abstract method, I'd say it doesn't belong in the base class in the first place.


    I agree that it prolly doesn't really belong in the base class.
    But how do I enforce the developers to implement the method?

    The issue is ppl keep checking in code that doesn't run. I would like to stop that.

  • User profile image
    Dr Herbie

    I have just tested this code and it works:

    public abstract class abstractClass
    {
       public abstract int Method(params DateTime[] dates);
    }

    public class DerivedClass1Param : abstractClass
    {
       public override int Method(params DateTime[] dates)
       {
          if (dates.Length != 1)
             throw new Exception("Too many dates, only expecting 1");

          return dates.Length;
       }
    }

    public class DerivedClass2Params : abstractClass
    {
       public override int Method(params DateTime[] dates)
       {
          if (dates.Length < 2)
             throw new Exception("Too few dates, expecting 2");

          if (dates.Length > 2)
             throw new Exception("Too many dates, only expecting 2");

          return dates.Length;
       }
    }


    Will that give you the functionality you need?

    You can call all overrides of Method with any number of DateTime parameters:

    actual = target.Method(DateTime.Now);
    actual = target.Method(DateTime.Now, DateTime.Now);

    or even (incorrectly)

    actual = target.Method(DateTime.Now, DateTime.Now, DateTime.Now);


    Derived classes will have to use their own internal code to validate the parameters.


    Herbie

  • User profile image
    phreaks

    Dr Herbie wrote:
    I have just tested this code and it works:

    public abstract class abstractClass
    {
       public abstract int Method(params DateTime[] dates);
    }

    public class DerivedClass1Param : abstractClass
    {
       public override int Method(params DateTime[] dates)
       {
          if (dates.Length != 1)
             throw new Exception("Too many dates, only expecting 1");

          return dates.Length;
       }
    }

    public class DerivedClass2Params : abstractClass
    {
       public override int Method(params DateTime[] dates)
       {
          if (dates.Length < 2)
             throw new Exception("Too few dates, expecting 2");

          if (dates.Length > 2)
             throw new Exception("Too many dates, only expecting 2");

          return dates.Length;
       }
    }


    Will that give you the functionality you need?

    You can call all overrides of Method with any number of DateTime parameters:

    actual = target.Method(DateTime.Now);
    actual = target.Method(DateTime.Now, DateTime.Now);

    or even (incorrectly)

    actual = target.Method(DateTime.Now, DateTime.Now, DateTime.Now);


    Derived classes will have to use their own internal code to validate the parameters.


    Herbie



    Thanks Herbie, that does effect the desired result.

    Danke.

  • User profile image
    Dr Herbie

    phreaks wrote:
    

    Thanks Herbie, that does effect the desired result.

    Danke.


    No problem.  I see it as having earned the right to sit and feel smug for a few moments.

    ...


    OK, smugness over.

    Herbie

Comments closed

Comments have been closed since this content was published more than 30 days ago, but if you'd like to continue the conversation, please create a new thread in our Forums, or Contact Us and let us know.