Object Inheritance - Save Function - Return Type forced to BaseClass

Object Inheritance - Save Function - Return Type forced to BaseClass

Old forum URL: forums.lhotka.net/forums/t/53.aspx


RanceDowner1234 posted on Tuesday, May 09, 2006

Hey all I'm a newbie to the CSLA.net framework, but so far I am finding it to be great, when creating non-inherited classes.  I've created several of these non-inherited classes in an accounting application I'm writing, but now I'm getting to a more complex part of the coding where I'm trying to implement Object Inheritance.

I have an object called PhoneCompanyStatement, derived from StatementBase, derived from LineItemBase, which is finally derived from BusinessBase(Of LineItemBase).  I will have other objects such as GasCompanyStatement, ElectricCompanyStatement, etc that derive from StatementBase too. 

It seems to be standard OOP.  My PhoneCompanyStatement has all but 4 public properties in common with a GasCompanyStatement, ElectricCompanyStatment, etc.  So I created a base class called StatementBase which contains some 20 properties that "all" statments have in common. 

In turn a "Statement" is just a "line item" which has fields in common with PaymentBase and PenaltyBase.  So I created a LineItemBase on which StatmentBase, PaymentBase, and PenaltyBase will all derive.

But while creating the Factory Methods I tried the following line of code I get two compile errors on the Save Override:

<System.Serializable()> _
Public Class PhoneCompanyStatement
    Inherits StatementBase 'Note: StatementBase inherits LineItemBase, which inherits BusinessBase(Of LineItemBase)

''' Other Code

#Region " Factory Methods "

    Public Overrides Function Save() As PhoneCompanyStatement
        Return MyBase.Save
    End Function

#End Region

''' Other Code

End Class

I get two compile errors:

Error    1    'Public Overrides Function Save() As PhoneCompanyStatement' cannot override 'Public Overridable Function Save() As LineItemBase' because they differ by their return types.   

Error    2    Option Strict On disallows implicit conversions from 'FeesDataObjects.LineItemBase' to 'FeesDataObjects.PhoneCompanyStatement'.

I can only make the compile errors go away if I change the return type of the save function to the lowest level BaseClass type.

    Public Overrides Function Save() As LineItemBase
        Return MyBase.Save
    End Function

Is this a good idea?  It just doesn't look right to me.  It doesn't seem standard OOP to me.  But maybe I'm wrong?

Has anybody worked with Inheritance chains like this before in CSLA.net.  And if so how did you implement the Save Function.

Thanks for any help.

Rance Downer
rancedowner1234@hotmail.com





Jav replied on Tuesday, May 09, 2006

My guess is that the reason the "compiler" likes LineItemBase is because that is the final type Of generic(for lack of a better term) you have declared.  In other words, I think, that you are saying that your inheritance looks like this:

Public Class LineItemBase
        Inherits Csla.BusinessBase(Of LineItemBase)

Public Class StatementBase
       Inherits LineItemBase

Public Class PhoneCompanyStatement
       Inherits StatementBase

As far as the Return value from Save is concerned, it is okay even if it is LineItemBase - you will just need to cast it back like:  
        Mystatement = CType(Mystatement.Save(), PhoneCompanyStatement)

and you will only need to do that if you are going to continue to use "MyStatement" object after the Save.  If you are not, it don't mean noth'n whatcha got back since y'all gonna squash it anyway.

Jav

Gigatron replied on Wednesday, May 10, 2006

I have have a similar need for my project.  Jav's suggestion helped, but my generics looked like this:

Public Class AddressBase(Of T As AddressBase(Of T))
      
Inherits BusinessBase(Of T)

End Class

Public Class CentreAddress
      
Inherits AddressBase(Of CentreAddress)

End Class

Is this correct way of approaching?  It compiles, but I haven't tested yet.

Jav replied on Wednesday, May 10, 2006

Gigatron

It looks like AddressBase is the final class in your inheritance.  If that is the case, then I would simply do this.

Public Class AddressBase
     Inherits Csla.BusinessBase(Of AddressBase)

Otherwise - if you do it your way, every place you have to express the Type of AddressBase, you will run into problems.  For example, when you declare

Private MyAddress As AddressBase

the compiler would not let you do that.

Jav

Jav replied on Wednesday, May 10, 2006

Gigatron
Sorry - I did not read your entire post.  Yes you are doing it right.
Jav

xal replied on Tuesday, May 09, 2006

Hey!

It sounds like you should be creating your base classes  generic.

Like


Public Class LineItemBase(Of T as LineItemBase)
    Inherits BusinessBase(Of T)
...
End Class

and

Public Class StatementBase(Of T as StatementBase)
    Inherits LineItemBase(Of T)
...
End Class


Your final class will be
Public Class PhoneCompanyStatement
    Inherits StatementBase(Of PhoneCompanyStatement)
...
End Class


I hope it helps!

Andrés

RanceDowner1234 replied on Wednesday, May 10, 2006

Thanks.  I will try the generics route. 

Most of the time I only call Save( ) as a subroutine for instance I'll say:

Call PhoneCompanyStatement.Save( )

But I just figured if other people in my company used my object it might be nice if they could count on the return value being passed back as same type as the object. 

I suppose it's not too bad if they cast it back like:

Dim myReturn As LineItemBase
myReturn = PhoneCompanyStatement.Save( )

Dim newObj As PhoneCompanyStatment
newObj = CType(myReturn, PhoneCompanyStatement)

But for some reason that just didn't seem right.

But if I have a hard time with the generics... as I've used generics before, but never built them... I'll go the Cast route instead. 

But for now, thanks for the advice on the generics.  I'll give that a schoolhouse try!

Much thanks to both of you for your help!

Rance

RanceDowner1234 replied on Wednesday, May 10, 2006

Just wanted to let you know.  The generics worked beautifully!!!  Gracias, gracias mi amigo.

I was a little nervous at first, but really it wasn't that hard to build.  It was just a matter of declaring the types correctly.  It was almost exactly as xal's code two threads above.  With one minor tweak.  I will post the change in case anyone else can benefit from the experience. 

Here's the Final Code...  The basic addition was the "(Of T)" lines...

Public MustInherit Class LineItemBase(Of T As LineItemBase(Of T))
    Inherits BusinessBase(Of T)

Public MustInherit Class StatementBase(Of T As StatementBase(Of T))
    Inherits LineItemBase(Of T)

Public Class PhoneCompanyStatement
    Inherits StatementBase(Of PhoneCompanyStatement)

    ''''Other factory methods like GetInstance(byval id as Integer)

    'This line works now!!!!
    Public Overrides Function Save() As PhoneCompanyStatement
        Return MyBase.Save
    End Function

End Class

Other code...

Dim Obj As PhoneCompanyStatement
Obj = PhoneCompanyStatement.GetInstance([id])

Dim copyObj As PhoneCompanyStatement
copyObj = Obj.Save( )

Thanks again Guys.  I might be able to use this generics stuff in other places now too!

Rance

xal replied on Wednesday, May 10, 2006

Oops!
How about having the forum engine compile the code samples we post? Smile [:)]
Or better yet, intellisense!

Sorry.
Anyway, I'm glad you found your way!

Andrés

lazaroms replied on Saturday, July 10, 2010

Hola Andrés:

¿Pudieras dejarme un correo para hacerte algunas consultas en español?

Saludos,

 

Lazaro Manuel Santin.

Lmsantin@yahoo.es

Copyright (c) Marimer LLC