Android Question How to access properties of "unknown" object?

Troberg

Well-Known Member
Licensed User
Longtime User
I have made a framework, where I can plug in GUI components by creating them as classes with a certain interface. Normally, I would do this using Implements, so that they would all appear to be the same class, but that option is not available in B4A.

So, in my case, I have a bunch of different GUI components (in the framework terminology called SCR). These are different, but they all share some common properties and methods.

So, for example, I want to do this:

B4X:
Sub ShowSCR(SCR As Object)
  SCR.HostPanel.Visible = True
End Sub

I know that SCR has a HostPanel property, which has a Visible property, but the compiler doesn't and reports an error.

How do I solve this, without true object oriented interfaces? For methods, it's easy to simply use CallSub (at least as long as they don't have many arguments), but properties?
 

Troberg

Well-Known Member
Licensed User
Longtime User
Ah, but SCR isn't a panel. SCR is not a single class, it's a bunch of different classes with a common interface, and one of the exposed properties in that interface is HostPanel.

So, the code fails at the first dot, after SCR.
 
Upvote 0

JordiCP

Expert
Licensed User
Longtime User
Then, this should work

B4X:
If SCR is someSpecificClass then
   Dim myP someSpecificClass =SCR
   myP.HostPanel.Visible=True
End if
 
Upvote 0

Troberg

Well-Known Member
Licensed User
Longtime User
Yes, but it would kind of break the idea of having a framework where the host (where this code resides) don't have to know anything about the components it hosts, other than that they all share a certain interface.

At the moment, I need one (or, if one is strict about counting, two) line of code to add a component. Example:

B4X:
'Add About SCR
Dim SCR As cSCRAbout :AddSCR(SCR)
'Add Video SCR
Dim SCR As cSCRVideo :AddSCR(SCR)

That's the only place where I need to know the actual type. Form then on, I don't want to have to add any special handling at all for different SCRs. For example, if I do this the following, I shouldn't need any special handling depending on if it's cSCRAbout or cSCRVideo, I just need to know that since they have all the methods and properties that the SCR interface demands, they should have an Enabled-property.

B4X:
Sub EnableSCR(SCR as object, Enabled as Boolean)
  SCR.Enabled=Enabled
End Sub

These are the very building blocks in my framework, and I'm going to use them a lot. I don't want to add specific code for each SCR (which may be dozens) in every specific place I access them.

I understand (or, at least I think I do) why Erel has chosen to not go down the full object oriented path, and I support those reasons, but in this case, it would have been easy to just define an iSCR interface, then specify on all SCRs that they Implements iSCR. THat way, I could have been able to simply handle them all as iSCR.
 
Upvote 0

Troberg

Well-Known Member
Licensed User
Longtime User
Ah, neat. I was going down a slightly similar path, using CallSub to directly call the getters and setters of the properties.

B4X:
Dim hp As Panel=CallSub(SCR, "getHostPanel")
hp.Visible = True

Your version is neater, though.
 
Upvote 0

JordiCP

Expert
Licensed User
Longtime User
There is even a third method using classes. It will allow exactly the syntax you were initially looking for :)

Define a generic class with all the common interface members, and methods if needed
B4X:
'CI_class <-- Common interface class
Sub Class_Globals
  Dim Property1 as Boolean
  Dim Property2 as Int
end sub
...

The classes which share this common interface will place the members in a CI_class instance
B4X:
' 
Sub Class_Globals
  ...
  Dim CI as CI_class 'place where all your common interface properties will be
end sub
...

and finally, your SCR object wouldn't have to be an object anymore, but a CI_class instance

B4X:
   'myClass1 and myClass2 have a CI_class
   Dim myClass1Var as myClass1
   Dim myClass2Var as myClass2
   myVar1Class.Initialize(...)
   myVar2Class.Initialize(...)

  Dim SCR1,SCR2 as CI_class
  SCR1=myClass1Var.CI
  SCR2=myClass2Var.CI

  'Then you can do
  SCR1.Property1=True
  SCR2.Property2=3
 
Upvote 0

Troberg

Well-Known Member
Licensed User
Longtime User
Neat, very neat, but it wouldn't be without problems either, as there would then be a discrepancy between myClass Me and SCR Me. I use messages to communicate between classes, and this would mean they ended up at the wrong class. All in all, it would be a bit backward to put myClass in control over the parent SCR if it's contained in it.

I'm sure I could work around that (for example but adding an Owner property to SCR), but it would require a bit too much rebuild at this point.

Just to clarify: Even though the SCRs share the same interface, they will be very different on the inside, and will have very different capabilities and responses. Getting a clean path through the interface to the inside might be a bit awkward.

And, yes, I'm picky. I'm going to use this framework extensively in a large project, so I want it as smooth as possible to use. :)
 
Upvote 0
Top