I am testing the valentina database api. However, my problem is more related to a general class and inheritance question. I use two classes from the api:
VDatabase (the database object reference)
VTable (the table object reference)
To get an instance of a table there is only one way to go: Call the VDatabase.Table method with the table name as parameter.
Valentina now suggests to subclass the VDatabase and VTable classes.
Example:
Class myDatabase As VDatabase
Class customers As VTable
The new inherited customers object could now contain specific code for data manipulation (like adding calculated fields etc.).
The problem is now: How do I get a customers instance? If I override the “table” method in the myDatabase class, I can generate a customers instance but it doesn’t contain the table. I can call the superclasses table method of course to get a VTable instance, but since there is no way of “downcasting” it to a customer instance that wouldn’t help me.
[quote=350605:@Eli Ott]Of course you can downcast a VTable to Customers:
Dim custs As Customers = Customers(theVTable)
This is unlikely to be possible in MOST cases
For instance
new desktop project
to Windows 1 add the Open event
in the open event put
Dim c As CustomClass1 = CustomClass1( foo )
add the “foo” method to Window1
Public Function foo() as Class1
return new Class1
End Function
add Class1
Class Class1
Property untitled as integer
Computed Property untitled1 as integer
end Class1
Class CustomClass1
inherits Class1
Property untitled2 as integer
Computed Property untitled3 as integer
end Class1
run and you’ll get an illegal cast exception
This set up is intentionally made to mimic what I suspect Valentina is doing (since it cant know the subtype to return from the VDatabase.Table method call)
Subclasses can safely be cast to be the super class type (because they ARE instance of the super class type)
Super class instances are unlikely to be able to be cast to subclass types
The recommendation to subclass the type is curious because of this
I just wondered because factory classes like the VDatabase class are a common design pattern in OOP. In Terms of inheritance this seems to be a dead end though. I just wondered if I missed something here.
[quote=350611:@Norman Palardy]Norman Palardy 11 minutes ago Xojo Inc Edited 9 minutes ago by Norman Palardy @Eli Ott Of course you can downcast a VTable to Customers:
Dim custs As Customers = Customers(theVTable)
This is unlikely to be possible in MOST cases
[/quote]
I did not suggest to cast the method .Table, I suggested to cast the returned table hence the name theVTable as there is no other way. More explicitly:
Dim theVTable As Variant = vdb.Table(...)
Dim custs As Customers = Customers(theVTable)
Did you even try this before making the suggestion ?
I’m not “casting a method”
I’d be casting the result the method returns
Which is the EXACT same thing regardless of the variant or not
Change the code I suggested to
dim v as variant = foo
Dim c As CustomClass1 = CustomClass1( v )
And you still get an illegal cast exception - going through a variant makes no difference
It doesn’t have any magic means to make a super class be a subclass instance
For exactly the reasons I outlined at the end of my post
Super class instances can NOT necessarily be cast to subclasses - there is one case where they are which is when the super & sub do NOT differ in any way so they have the EXACT same vtables memory layout etc
An then why bother having the subclass since its identical to the super ?
@Eli Ott
I think the problem here is that casting just points the compiler to the fact that an instance corresponds to a certain subclass, even if it has been originally declared as some of it’s superclasses. There is no conversion of instances taking place. As Norman pointed out the superclass cannot know about subcasses.
I understood the OP in that he was supposed so subclass VDatabase and VTable. Then you override VDatabase.Table(name) along this:
Function VDatabaseSubclass.Table(name As String) As VTable
Dim tmp As VTable = Super.Table(name)
Select Case name
Case "Customer"
Dim cust As New VCustomer // VCustomer is a subclass of VTable
cust.Prop1 = tmp.Prop1
cust.Prop2 = tmp.Prop2
...
cust.PropN = tmp.PropN
Return cust
Case "Employee"
...
Else
Return tmp
End
End
Then the caller can cast the result (indirectly via a Variant, Auto or VTable variable).
I should have included the following quote in my post:
… or where else could he have called New Customer()?
New YourSubclass() is needed. The only case where it wouldn’t be needed is if one could register pairs of table names with introspection’s type infos. Then the VDatabase class could return subclasses of VTable. But the Valentina API doesn’t contains something like that.