Abstract Class & Inheritance

Last post 05-03-2006 2:01 PM by cmay. 21 replies.

Sort Posts:

  • Abstract Class & Inheritance

    05-01-2006, 12:54 PM
    • Member
      105 point Member
    • djdouma
    • Member since 10-30-2003, 2:10 PM
    • Posts 24

    I'm new to defining abstract classes, so bear with me here.  I'd like to have a BaseObject with the following two Methods; Delete & Add

    When I inherit BaseObject into ChildObject1 and ChildObject2, how do I have a different parameter list for the Add Method?

    I've posted "example" code below of what I'm trying to accomplish.  Thanks in advance for your help.

    public abstract class BaseObject 
    { 
    
     public abstract void Add(); 
    
     public abstract void Delete(int Id); 
    } 
    public class ChildObject1 : BaseObject 
    { 
    
     public override void Add(string Name, string Desc) 
     { 
     } 
    
     public override void Delete(int Id) 
     { 
     } 
    } 
    public class ChildObject2 : BaseObject 
    { 
    
     public override void Add(string Name) 
     { 
     } 
    
     public override void Delete(int Id) 
     { 
     } 
    } 
    struct TestModule 
    { 
    
     void Main() 
     { 
       ChildObject1 child1 = new ChildObject1(); 
       child1.add("Testing Child1"); 
       ChildObject2 child2 = new ChildObject2(); 
       child2.add("Testing Child2", "My Description"); 
     } 
    }
     
  • Re: Abstract Class & Inheritance

    05-01-2006, 2:47 PM
    • Participant
      875 point Participant
    • James Steele
    • Member since 04-27-2006, 12:08 AM
    • Posts 173

    Although an override method can provide a new implementation of an inherited abstract method of the base class it cannot modify the signature. In your case, your derived classes must provide an implementation of the Add method that accepts no arguments. From that point you can then provide overloaded methods of the Add method.

     public class ChildObject1 : BaseObject
     {
    
         public override void Add()
         {
         }
    
         public void Add(string Name, string Desc)
         {
         }
    
         public override void Delete(int Id)
         {
         }
     }
     James Steele
  • Re: Abstract Class & Inheritance

    05-01-2006, 3:09 PM
    • Member
      105 point Member
    • djdouma
    • Member since 10-30-2003, 2:10 PM
    • Posts 24

    Thanks James.  That make sense.

    Is there a way to 'hide' the overriden method Add() so that objects that inherit ChildObject1 won't be able to use this method?

  • Re: Abstract Class & Inheritance

    05-01-2006, 6:39 PM
    • Participant
      875 point Participant
    • James Steele
    • Member since 04-27-2006, 12:08 AM
    • Posts 173
    Not that I know of, but I would like to make a suggestion if you do not mind. If that specific Add() method - the one with no arguments - is not mandatory in the inherited class (with no arguments) then it really should not me marked as abstract. Abstract indicates that it MUST be implemented in the inherited class (and that includes the matching signature, in this case no arguments). But what you are really telling me is that the Add method with no arguments is not necessarily a must in the inherited class.

    Common practice in this scenario is to make the method virtual and have it throw a NotSupportedException.  
     public abstract class BaseObject
        {
            public virtual void Add() 
            {
                throw new NotSupportedException("Add with no arguments is not supported");
            }
    
            public abstract void Delete(int Id);
        } 
    
        public class ChildObject1 : BaseObject 
        { 
    
            public void Add(string Name, string Desc) 
            { 
            } 
    
            public override void Delete(int Id) 
            { 
            } 
        } 

    Bottom line is that if a feature(that includes its corresponding signature) is going to be optional in the inherited class then do not mark it abstract. If its mandatory then mark it abstract but include all possible signatures in the base class.

    Hope that helps.

    James Steele
  • Re: Abstract Class & Inheritance

    05-01-2006, 8:02 PM
    • Member
      208 point Member
    • cmay
    • Member since 02-21-2006, 10:59 AM
    • Chicago
    • Posts 44
    You might want to look into "Shadows".
     
    It won't solve your exact problem, but if you have a base class with a method called "Add(integer i)" and you want your inheriting class to have some other "Add" for example "Add(string s, bool b)" you can declare it as shadows, and it will "hide" the base classes Add without messing up the base class functionality.
  • Re: Abstract Class & Inheritance

    05-01-2006, 8:13 PM
    • Participant
      875 point Participant
    • James Steele
    • Member since 04-27-2006, 12:08 AM
    • Posts 173
    .....which is similar to the "new" modifier in C#.

    James Steele
  • Re: Abstract Class & Inheritance

    05-02-2006, 4:38 AM
    • Member
      665 point Member
    • biswajitdash
    • Member since 06-21-2002, 7:06 AM
    • Bangalore, India
    • Posts 133
    And how exactly you make methods shadow in C#, where the method signature itself differs? Can you give working example code?
    Biswajit Dash
  • Re: Abstract Class & Inheritance

    05-02-2006, 11:44 AM
    • Member
      469 point Member
    • idof
    • Member since 02-04-2006, 12:43 PM
    • Israel
    • Posts 96

    Hi,

    As you've been explained, this is not the usual use of an abstract class. BTW, if you wish to do the above, you'd better use interfaces (call it IUpdatableObject for example).

    As for the parameters - if you use .net 2.0, you can use generics and declare the parameter type as T.

    for example:

    interface IUpdatableObject<T>

    {

    void update(T newData);

    }

    class Implementor : IUpdatableObject<string>

    {

    public void update(string newData)

    }

    If you need to use multiple parameters, just declare a custom class/struct to hold those parameters (which actually makes it a data structure).

    Best of luck,

    Ido.

  • Re: Abstract Class & Inheritance

    05-02-2006, 12:10 PM
    • Member
      105 point Member
    • djdouma
    • Member since 10-30-2003, 2:10 PM
    • Posts 24

    Ido, thanks for your comments.  Would you be able to provide a code example which follows along the lines of what I originally posted (two methods, Delete & Add, with two Classes implementing Add with two different parameter lists)?  I work better with examples Wink [;)] 

    public abstract class BaseObject 
    { 
    
     public abstract void Add(); 
    
     public abstract void Delete(int Id); 
    } 
    public class ChildObject1 : BaseObject 
    { 
    
     public override void Add(string Name, string Desc) 
     { 
     } 
    
     public override void Delete(int Id) 
     { 
     } 
    } 
    public class ChildObject2 : BaseObject 
    { 
    
     public override void Add(string Name) 
     { 
     } 
    
     public override void Delete(int Id) 
     { 
     } 
    } 
    struct TestModule 
    { 
    
     void Main() 
     { 
       ChildObject1 child1 = new ChildObject1(); 
       child1.add("Testing Child1"); 
       ChildObject2 child2 = new ChildObject2(); 
       child2.add("Testing Child2", "My Description"); 
     } 
    }
     
  • Re: Abstract Class & Inheritance

    05-02-2006, 12:22 PM
    • Member
      208 point Member
    • cmay
    • Member since 02-21-2006, 10:59 AM
    • Chicago
    • Posts 44
    Maybe I misspoke here.
     
    I tried to do it in C# and it would always show the base interface as well (it indicated that the method was from the base class and not the subclass, but still I couldn't hide that inteface).
     
    In VB.Net you can indeed hid the interface of the base class using Shadows.
     
    Maybe someone else can tell me if there is no way to do this with C#.  I figured b/c you could do it in VB you could in C#.
     
    Public Class Base
        Public Function Add(ByVal i As Integer, ByVal n As Integer) As Integer
            Return i + n
        End Function
    End Class
    
    Public Class SubClass
        Inherits Base
    
        Public Shadows Function Add(ByVal i As Integer, ByVal x As Integer, ByVal y As Integer) As Integer
            Return MyBase.Add(i, x) + y
        End Function
    End Class
      
        public abstract class Abst
        {
            public abstract string AbstMethod();
    
            public  string Add(int i, int n)
            {
                int ret = (i + n);
    
                return ret.ToString();
            }
        }
    
        public class Conc : Abst
        {
            public override string AbstMethod()
            {  
                return "Whatever";
            }
            
            public new string Add(int i, int n, int x)
            {
                int basevalue = int.Parse(base.Add(i, n));
                basevalue = basevalue + x;
                return basevalue.ToString();
            }
        }
     
  • Re: Abstract Class & Inheritance

    05-02-2006, 2:42 PM
    • Participant
      1,001 point Participant
    • TAsunder
    • Member since 12-29-2005, 7:11 PM
    • Posts 215

    I don't get it.  Why do you want to do this?  It makes no sense.  Is it just so that when you type the . after the object it shows an add method?  It really does not offer you any of the flexibility of polymorphism when you do this.  If your base method is to be at all meaningful or useful and not just wasted code to confuse developers, you need to abstract the method parameters too.

    Maybe you need an AddParameters class.  By default this has no members.  In your individual Add() methods you make sure that the class passed in to the Add method is of the minimal type needed (i.e. you need an object that inherits from AddParameters that has an Int).

  • Re: Abstract Class & Inheritance

    05-02-2006, 2:57 PM
    • Member
      208 point Member
    • cmay
    • Member since 02-21-2006, 10:59 AM
    • Chicago
    • Posts 44
    You don't lose any polymorphism doing this.  That is why the method shadows the inherited classes methods.
     
    Obviously I wasn't trying to put a lot of real world relevance into my example with my Add method.
     
    The issue is that there may be times when you want to inherit from a class and have a simliar named method with a different signature, maybe do different things, without breaking anything in the base class.
     
    You don't always have access to the source code to change the class you are inheriting from, and you don't always want to change the base class anyway.
     
    If I use shadows on a method and you pass the object polymorphically as its base class's type, then the base class "Add" method will be available, not the shadows method, so polymorphism is fully available.
  • Re: Abstract Class & Inheritance

    05-03-2006, 12:20 AM
    • Member
      665 point Member
    • biswajitdash
    • Member since 06-21-2002, 7:06 AM
    • Bangalore, India
    • Posts 133

    You don't lose any polymorphism doing this.  That is why the method shadows the inherited classes methods.

    What TAsunder asked is correct. Look at the following code block to explain the polymorphic scenario better. The VB.NET way of shadowing really does not satisfy any polymorphism. Assume that the classes are written in VB.NET library and referred from a C# client.


    ' VB.NET Class Library
    Public Class BaseClass
        Public Function Add(ByVal i As Integer,
                            ByVal j As Integer) As Integer
            Return i + j
        End Function
    End Class


    Public Class DerivedClass
        Inherits BaseClass

        Public Shadows Function Add(ByVal i As Integer,
                                    ByVal j As Integer,
                                    ByVal k As Integer) As Integer
            Return MyBase.Add(i, j) + k
        End Function
    End Class

     

    // C# Class Library
    public class ClientClass
    {
        public static void Main()
        {
           
            BaseClass b = new BaseClass();
            DerivedClass d = new DerivedClass();
            BaseClass objRef = null;

            // Polymorphic call here. Will work fine.
            objRef = b;
            objRef.Add(1, 2); // Will work.

            // Polymorphic call here. Will fail. Because
            // type BaseClass does not have any Add() 
            // method that takes 3 arguments.
            objRef = _d;
            objRef.Add(1, 2, 3); // Will fail.
        }
    }



    So, a polymorphic call in run-time will fail. Also following shadowing technique in real-life violates LSP at the best. Any design using this must be avoided.

    Biswajit Dash
  • Re: Abstract Class & Inheritance

    05-03-2006, 1:10 AM
    • Member
      208 point Member
    • cmay
    • Member since 02-21-2006, 10:59 AM
    • Chicago
    • Posts 44
    biswajitdash:

    You don't lose any polymorphism doing this.  That is why the method shadows the inherited classes methods.

    What TAsunder asked is correct. Look at the following code block to explain the polymorphic scenario better. The VB.NET way of shadowing really does not satisfy any polymorphism. Assume that the classes are written in VB.NET library and referred from a C# client.


    ' VB.NET Class Library
    Public Class BaseClass
        Public Function Add(ByVal i As Integer,
                            ByVal j As Integer) As Integer
            Return i + j
        End Function
    End Class


    Public Class DerivedClass
        Inherits BaseClass

        Public Shadows Function Add(ByVal i As Integer,
                                    ByVal j As Integer,
                                    ByVal k As Integer) As Integer
            Return MyBase.Add(i, j) + k
        End Function
    End Class

     

    // C# Class Library
    public class ClientClass
    {
        public static void Main()
        {
           
            BaseClass b = new BaseClass();
            DerivedClass d = new DerivedClass();
            BaseClass objRef = null;

            // Polymorphic call here. Will work fine.
            objRef = b;
            objRef.Add(1, 2); // Will work.

            // Polymorphic call here. Will fail. Because
            // type BaseClass does not have any Add() 
            // method that takes 3 arguments.
            objRef = _d;
            objRef.Add(1, 2, 3); // Will fail.
        }
    }



    So, a polymorphic call in run-time will fail. Also following shadowing technique in real-life violates LSP at the best. Any design using this must be avoided.

     

    Sorry but your code example is backwards in terms of understanding how polymorphism and LSP works.

    Polymorphism works by allowing you to say that a DerivedClass can be used as a BaseClass.  But you are trying to use a BaseClass as a DerivedClass.  Polymorphism doesn't work in that direction.

    Your line of code:
    objRef.Add(1, 2, 3); // Will fail.

    Of course it will fail.  It won't even compile.  objRef is a BaseClass.  BaseClass doesn't have a method "Add" that takes 3 parameters.

    What if DerivedClass defines a method "Subtract".  objRef won't have that either.  It's the same thing.  Base Classes don't know about the classes that inherit from them.

    But if you case objRef as a DerivedClass, then you can call Add with 2 or 3 parameters, just as you would expect to.

    If what you coded worked (objRef.Add(1,2,3)) then THAT is what would break LSP. 

    But LSP is not violated.  I modified your code a little to show that LSP is not violated, and polymorphism remains fully functional.

    See my code example to clear this up:

     

     
    ' VB.NET Class Library
    
    Public Class BaseClass
        Public Function Add(ByVal i As Integer, _
                            ByVal j As Integer) As Integer
            Return i + j
        End Function
    
        Public Function LSP() As String
            Return "I am LSP compliant"
        End Function
    End Class
    
    
    Public Class DerivedClass
        Inherits BaseClass
    
        Public Shadows Function Add(ByVal i As Integer, _
                                    ByVal j As Integer, _
                                    ByVal k As Integer) As Integer
            Return MyBase.Add(i, j) + k
        End Function
    
        Public Shadows Function LSP() As String
            Return "I am NOT LSP compliant, bad programmer"
        End Function
    End Class

     

     

     

     
    static void Main(string[] args)
            {
                
                BaseClass b = new BaseClass();
                DerivedClass d = new DerivedClass();
                BaseClass objRef = null;
    
                // Polymorphic call here. Will work fine.
                objRef = b;
                objRef.Add(1, 2); // Will work.
    
                // Polymorphic call here. Will fail. Because 
                // type BaseClass does not have any Add() 
                // method that takes 3 arguments.
                objRef = d;
    
                
                //objRef.Add(1, 2, 3); // Will fail.
                /**************
                 * My Comments: of course this will fail... 
                 * It will fail at compile time.  objRef is a BaseClass. 
                 * BaseClass doesn't have Add(i,i,i)  */
    
                // this will work just fine.
                ((DerivedClass)objRef).Add(1, 2, 3);
    
                // lets make sure LSP is not violated
                Console.WriteLine(testLsp(b));
                Console.WriteLine(testLsp(d));
                Console.WriteLine(testLsp(objRef));
                Console.WriteLine(testLsp((DerivedClass)objRef));
                Console.WriteLine("All passed");
                Console.Read();
            }
    
            static string testLsp(BaseClass b)
            {
                return b.LSP();
            }
     
  • Re: Abstract Class & Inheritance

    05-03-2006, 3:05 AM
    • Member
      665 point Member
    • biswajitdash
    • Member since 06-21-2002, 7:06 AM
    • Bangalore, India
    • Posts 133

    Sorry but your code example is backwards in terms of understanding how polymorphism and LSP works.

    Polymorphism works by allowing you to say that a DerivedClass can be used as a BaseClass.  But you are trying to use a BaseClass as a DerivedClass.  Polymorphism doesn't work in that direction.

    What you are telling in essence means that "Prgram to the concrete implementation and not the abstract/interface". Is it? Thats not correct. I guess most in this forum will disagree on what you are telling.

    The actual principle is - "Always program to an abstract/interface and not an implementation." Thats how polymorphiism is used. Otherwise why does the concept of interface exist?

     

    Biswajit Dash
Page 1 of 2 (22 items) 1 2 Next >