Inheritance Design Question

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Mike

    Inheritance Design Question

    I want to provide an abstract class to derive all nodes from. In the example
    below Parent in the base class is of Type Node, but in the custom class I
    want Parent to return a Type CustomNode. When CustomNode is accessed by a
    helper class as Node Parent is always null. Is this a poor design, Im sure
    it's a common problem and I am just missing something.

    Note: I use virtual for Parent because abstract will not compile.

    public abstract class Node
    {
    public virtual Node Parent
    {
    get { return null; }
    }
    public virtual bool IsLastChild
    {
    get { return this._isLastChi ld; }
    }
    private bool _isLastChild = false;
    }

    public class CustomNode : Node
    {
    public new CustomNode Parent
    {
    get { return this._customNod e; }
    }
    private CustomNode _customNode = null;
    }


  • Thomas P. Skinner [MVP]

    #2
    Re: Inheritance Design Question

    You need to use override rather than new in the derived class.

    Thomas P. Skinner [MVP]

    "Mike" <mikenospam@com .nospam> wrote in message
    news:O7R%23Qvj0 EHA.1404@TK2MSF TNGP11.phx.gbl. ..[color=blue]
    >I want to provide an abstract class to derive all nodes from. In the
    >example
    > below Parent in the base class is of Type Node, but in the custom class I
    > want Parent to return a Type CustomNode. When CustomNode is accessed by a
    > helper class as Node Parent is always null. Is this a poor design, Im
    > sure
    > it's a common problem and I am just missing something.
    >
    > Note: I use virtual for Parent because abstract will not compile.
    >
    > public abstract class Node
    > {
    > public virtual Node Parent
    > {
    > get { return null; }
    > }
    > public virtual bool IsLastChild
    > {
    > get { return this._isLastChi ld; }
    > }
    > private bool _isLastChild = false;
    > }
    >
    > public class CustomNode : Node
    > {
    > public new CustomNode Parent
    > {
    > get { return this._customNod e; }
    > }
    > private CustomNode _customNode = null;
    > }
    >
    >[/color]


    Comment

    • Mike

      #3
      Re: Inheritance Design Question

      Override does not work when changing the return Type, I want to return
      CustomNode which derives from Node.


      Comment

      • David Browne

        #4
        Re: Inheritance Design Question


        "Mike" <mikenospam@com .nospam> wrote in message
        news:e9XRy4j0EH A.1152@TK2MSFTN GP14.phx.gbl...[color=blue]
        > Override does not work when changing the return Type, I want to return
        > CustomNode which derives from Node.
        >[/color]

        You really should return Node. You are free to cast it to CustomNode if you
        know it is a CustomNode.

        David


        Comment

        • Nick Malik

          #5
          Re: Inheritance Design Question

          Your design problem is not clear. I understand what you are trying to do,
          but not why, so it is difficult to help.

          It is clear that a node has a parent. It is not clear why a childnode would
          need to return anything except a node type for its parent, because this
          restricts the entire tree that you can describe.

          What design pattern are you attempting to implement? Can you do this using
          the Visitor pattern? (http://home.earthlink.net/~huston2/dp/visitor.html)

          --- Nick

          "Mike" <mikenospam@com .nospam> wrote in message
          news:e9XRy4j0EH A.1152@TK2MSFTN GP14.phx.gbl...[color=blue]
          > Override does not work when changing the return Type, I want to return
          > CustomNode which derives from Node.
          >
          >[/color]


          Comment

          • Mike

            #6
            Re: Inheritance Design Question

            Since CustomNode is a Node, then any code expecting a node has a Node, but
            other code written for CustomNode gets a CustomNode, and no casting is
            needed. If there is a way to redesign these classes to work without casting
            I am al for it as it will reduce runtime errors associated with casting.

            It seems odd that the CustomNode #1 below works, because the compiler knows
            that _customNode is a Node, but #2 does not, when CustomNode derives from
            node. I cannot imagine any situation where #2 would cause a problem.
            --What am I missing here?

            #1) Works:

            public class CustomNode : Node
            {
            public override Node Parent
            {
            get { return this._customNod e; }
            }
            private CustomNode _customNode = null;
            }

            #2) Does Not Work:
            public class CustomNode : Node
            {
            public override CustomNode Parent
            {
            get { return this._customNod e; }
            }
            private CustomNode _customNode = null;
            }


            Comment

            • Mike

              #7
              Re: Inheritance Design Question

              Nick,

              Consider that CustomNode has:

              public string Description
              public string GetParentDecrip tions(CustomNod e node)
              {
              // loop node parents and return a string containing all parent
              descriptions
              }


              "Nick Malik" <nickmalik@hotm ail.nospam.com> wrote in message
              news:Ss2pd.1416 11$HA.65182@att bi_s01...[color=blue]
              > Your design problem is not clear. I understand what you are trying to do,
              > but not why, so it is difficult to help.
              >
              > It is clear that a node has a parent. It is not clear why a childnode[/color]
              would[color=blue]
              > need to return anything except a node type for its parent, because this
              > restricts the entire tree that you can describe.
              >
              > What design pattern are you attempting to implement? Can you do this[/color]
              using[color=blue]
              > the Visitor pattern? (http://home.earthlink.net/~huston2/dp/visitor.html)
              >
              > --- Nick
              >
              > "Mike" <mikenospam@com .nospam> wrote in message
              > news:e9XRy4j0EH A.1152@TK2MSFTN GP14.phx.gbl...[color=green]
              > > Override does not work when changing the return Type, I want to return
              > > CustomNode which derives from Node.
              > >
              > >[/color]
              >
              >[/color]


              Comment

              • David Browne

                #8
                Re: Inheritance Design Question


                "Mike" <mikenospam@com .nospam> wrote in message
                news:ONS2pIk0EH A.2200@TK2MSFTN GP09.phx.gbl...[color=blue]
                > Since CustomNode is a Node, then any code expecting a node has a Node, but
                > other code written for CustomNode gets a CustomNode, and no casting is
                > needed. If there is a way to redesign these classes to work without
                > casting
                > I am al for it as it will reduce runtime errors associated with casting.
                >
                > It seems odd that the CustomNode #1 below works, because the compiler
                > knows
                > that _customNode is a Node, but #2 does not, when CustomNode derives from
                > node. I cannot imagine any situation where #2 would cause a problem.
                > --What am I missing here?
                >[/color]

                You are correct, there's no reason why it couldn't be made to work. It just
                doesn't happen to.

                The feature is called "covariant return types". Java 5 and C++ and various
                other OO languages support it. .NET does not.

                David


                Comment

                • David Browne

                  #9
                  Re: Inheritance Design Question


                  "Mike" <mikenospam@com .nospam> wrote in message
                  news:%23snjqLk0 EHA.2192@TK2MSF TNGP14.phx.gbl. ..[color=blue]
                  > Nick,
                  >
                  > Consider that CustomNode has:
                  >
                  > public string Description
                  > public string GetParentDecrip tions(CustomNod e node)
                  > {
                  > // loop node parents and return a string containing all parent
                  > descriptions
                  > }
                  >
                  >[/color]

                  For this, you can just access the private member _customNode. You aren't
                  limited to to the virtual accessor when implementing methods on the type.


                  public string GetParentDecrip tions(CustomNod e node)
                  {
                  StringBuilder sb = new StringBuilder() ;
                  CustomNode parent = node._customNod e;
                  while (parent != null)
                  {
                  sb.Append(paren t.Description);
                  parent = parent._customN ode;
                  }
                  return sb.ToString();

                  }

                  David


                  Comment

                  • Mike

                    #10
                    Re: Inheritance Design Question

                    David,

                    Would you say in this case, the proper solution would be to provide...

                    public CustomNode CustomNodeParen t

                    ....this seems like the only way to avoid casting, but it feels clunky and
                    maybe there is another way, or this is a poor design.


                    "David Browne" <davidbaxterbro wne no potted meat@hotmail.co m> wrote in
                    message news:uCvS7Yk0EH A.2788@TK2MSFTN GP15.phx.gbl...[color=blue]
                    >
                    > "Mike" <mikenospam@com .nospam> wrote in message
                    > news:ONS2pIk0EH A.2200@TK2MSFTN GP09.phx.gbl...[color=green]
                    > > Since CustomNode is a Node, then any code expecting a node has a Node,[/color][/color]
                    but[color=blue][color=green]
                    > > other code written for CustomNode gets a CustomNode, and no casting is
                    > > needed. If there is a way to redesign these classes to work without
                    > > casting
                    > > I am al for it as it will reduce runtime errors associated with casting.
                    > >
                    > > It seems odd that the CustomNode #1 below works, because the compiler
                    > > knows
                    > > that _customNode is a Node, but #2 does not, when CustomNode derives[/color][/color]
                    from[color=blue][color=green]
                    > > node. I cannot imagine any situation where #2 would cause a problem.
                    > > --What am I missing here?
                    > >[/color]
                    >
                    > You are correct, there's no reason why it couldn't be made to work. It[/color]
                    just[color=blue]
                    > doesn't happen to.
                    >
                    > The feature is called "covariant return types". Java 5 and C++ and[/color]
                    various[color=blue]
                    > other OO languages support it. .NET does not.
                    >
                    > David
                    >
                    >[/color]


                    Comment

                    • Mike

                      #11
                      Re: Inheritance Design Question

                      Good point, but another class ( CustomNodeWrite r ) that does not have
                      private or protected access needs to navigate a CustomNode tree Parent will
                      have to return a Node and I am back to casting. It seems that adding: public
                      CustomNode CustomParent, is the only real solution here.



                      "David Browne" <davidbaxterbro wne no potted meat@hotmail.co m> wrote in
                      message news:e6bxKbk0EH A.3452@TK2MSFTN GP14.phx.gbl...[color=blue]
                      >
                      > "Mike" <mikenospam@com .nospam> wrote in message
                      > news:%23snjqLk0 EHA.2192@TK2MSF TNGP14.phx.gbl. ..[color=green]
                      > > Nick,
                      > >
                      > > Consider that CustomNode has:
                      > >
                      > > public string Description
                      > > public string GetParentDecrip tions(CustomNod e node)
                      > > {
                      > > // loop node parents and return a string containing all parent
                      > > descriptions
                      > > }
                      > >
                      > >[/color]
                      >
                      > For this, you can just access the private member _customNode. You aren't
                      > limited to to the virtual accessor when implementing methods on the type.
                      >
                      >
                      > public string GetParentDecrip tions(CustomNod e node)
                      > {
                      > StringBuilder sb = new StringBuilder() ;
                      > CustomNode parent = node._customNod e;
                      > while (parent != null)
                      > {
                      > sb.Append(paren t.Description);
                      > parent = parent._customN ode;
                      > }
                      > return sb.ToString();
                      >
                      > }
                      >
                      > David
                      >
                      >[/color]


                      Comment

                      • David Browne

                        #12
                        Re: Inheritance Design Question


                        "Mike" <mikenospam@com .nospam> wrote in message
                        news:uBv5qdk0EH A.2676@TK2MSFTN GP12.phx.gbl...[color=blue]
                        > David,
                        >
                        > Would you say in this case, the proper solution would be to provide...
                        >
                        > public CustomNode CustomNodeParen t
                        >
                        > ...this seems like the only way to avoid casting, but it feels clunky and
                        > maybe there is another way, or this is a poor design.
                        >[/color]

                        If CustomNode is an important subclass, that's what I would do.

                        The other solution is to switch node to an interface and use explicit
                        interface implementation for the parent method. Then you are free to
                        implement subtype-returning Parent methods on each subclass. I'm not sure
                        that's a better solution, though.


                        David


                        Comment

                        • Nick Malik

                          #13
                          Re: Inheritance Design Question

                          I am convinced that you can solve this problem with the Visitor pattern.



                          No casting is required and you do not need to use the _customNode property,
                          nor limit yourself to methods that return one object type.

                          The problem is solved... it is up to you to understand the solution.

                          --- Nick

                          "Mike" <mikenospam@com .nospam> wrote in message
                          news:%23snjqLk0 EHA.2192@TK2MSF TNGP14.phx.gbl. ..[color=blue]
                          > Nick,
                          >
                          > Consider that CustomNode has:
                          >
                          > public string Description
                          > public string GetParentDecrip tions(CustomNod e node)
                          > {
                          > // loop node parents and return a string containing all parent
                          > descriptions
                          > }
                          >
                          >
                          > "Nick Malik" <nickmalik@hotm ail.nospam.com> wrote in message
                          > news:Ss2pd.1416 11$HA.65182@att bi_s01...[color=green]
                          > > Your design problem is not clear. I understand what you are trying to[/color][/color]
                          do,[color=blue][color=green]
                          > > but not why, so it is difficult to help.
                          > >
                          > > It is clear that a node has a parent. It is not clear why a childnode[/color]
                          > would[color=green]
                          > > need to return anything except a node type for its parent, because this
                          > > restricts the entire tree that you can describe.
                          > >
                          > > What design pattern are you attempting to implement? Can you do this[/color]
                          > using[color=green]
                          > > the Visitor pattern?[/color][/color]
                          (http://home.earthlink.net/~huston2/dp/visitor.html)[color=blue][color=green]
                          > >
                          > > --- Nick
                          > >
                          > > "Mike" <mikenospam@com .nospam> wrote in message
                          > > news:e9XRy4j0EH A.1152@TK2MSFTN GP14.phx.gbl...[color=darkred]
                          > > > Override does not work when changing the return Type, I want to return
                          > > > CustomNode which derives from Node.
                          > > >
                          > > >[/color]
                          > >
                          > >[/color]
                          >
                          >[/color]


                          Comment

                          Working...