Scope

Ok… heres another one

Two Classes “A” and “B”
Class “A” has as a property a collection of Class “B”, and it manipulates properties of Class “B”
Class “A” also needs to return an instance of a specific Class “B” to the calling program (currently selected record if you will)
HOWEVER, there are two properties the Class “B” has, that I DO NOT want exposed to the calling program.

How (or can) I make selected properties “Private” to the “world”, but exposed to Class “A” only?

What you’re looking for is “friend” from C++
There’s no such thing

BUT
Put Class A and Class B in a module so they are namespaced
Add a Private interface to the module
Have class B implement it - and yes you can use private methods to satisfy an interface
Now Class A can use the private interface to manipulate Class B instances
Nothing else can

Aaron discussed this ages ago and I think its in his book
https://web.archive.org/web/20081025003104/http://ramblings.aaronballman.com/2008/05/friend_support_1.html

EDIT - aw crum thats the wrong one

What I do is 1) make the property private or protected in B with an accessor method, then 2) use a delegate in A to get access to that method. Basically delegates and Introspection break scope. This doesn’t make it impossible for others places to get access, but not any more than there already is :slight_smile:

Put Class A and Bi in a module, Create an interface that is private to the module that case B implements with a protected method. Nothing outside the module knows about the interface.

  • Karen

The private interface makes it impossible for things outside to get at it
Now if only I can find aaron’s article

There it is

https://web.archive.org/web/20071026040424/http://ramblings.aaronballman.com/2007/06/friend_support.html

Ok… I read Aarons article, I read Section 5 of the user guide, and I know less now that I did 1/2 hour ago.
Everything seems centered around the statement getting two classes that don’t share a Super to do similar things

I created a Module, I moved the two classes into that Module, I added an Interface to the Module…
but am at a total loss as to what I’m supposed to to with or to that interface

Class A has a collection of B objects
right now it has code in varioius places that

array_of_B(index).xyz=true

Class B has a computed Property called XYZ where the Setter updates a local variable, and decides if certain actions should occur

Class A also needs to expose an instance of CLASS B to the calling program, BUT NOT expose XYZ (xyz is read/write, all the other properites are GETTER only),

For those computed properties you want only ClassA to see, make them private. Actually, I think you also have to make them regular methods. Then create an interface for those methods and put that in the module too. Make the interface private and add the interface to ClassB.

Now those methods in ClassB are private so anything outside the module can’t access them. But ClassA can access them through the interface, and only things in the module can see the interface.

MyInterface(array_of_B(index)).xyz = true

[quote=175502:@Will Shank]For those computed properties you want only ClassA to see, make them private. Actually, I think you also have to make them regular methods. Then create an interface for those methods and put that in the module too. Make the interface private and add the interface to ClassB.

Now those methods in ClassB are private so anything outside the module can’t access them. But ClassA can access them through the interface, and only things in the module can see the interface.

MyInterface(array_of_B(index)).xyz = true

No offense Will… but “create an interface for those methods”… that seems to be the part everyone keeps telling me, but that I keep saying I don’t understand…

Correct me if I am wrong, but couldn’t you call parameters not to fetch those properties? Perhaps I am not understanding the question…

Oh, It’s that xyz method. So I’m seeing you want to call xyz on ClassB from ClassA only. Make an interface and put all those methods into it and then add the interface to ClassB (which already has the interface implemented :slight_smile: )

Class ClassB Sub xyz(assigns val As Boolean) End Class

turns into

[code]Module MyModule

Class ClassA
Sub test()
dim b As new ClassB
MyInterface(b).xyz = true
End Sub
End Class

Private Interface MyInterface
Sub xyz(assigns val As Boolean)
End Interface

Class ClassB
Private Sub xyz(assigns val As Boolean)
End Class

End Module[/code]

*may have errors but it’s the idea as i understand it

To do this via delegates you’d define a delegate type in ClassA for each private method you want access to in ClassB. Then in ClassA (and ClassA only) you can write…

[code]dim d As MyDelegate = AddressOf objB.privateMethod
d.Invoke(params)

//or

MyDelegate(AddressOf objB.privateMethod).Invoke(params)[/code]

The syntax is definitely clunkier than an interface, but if the classes aren’t or you don’t want them to be in the same module this is a way for access. And possibly simpler if there’s only 1 or 2 methods needing access a single time.

It won’t let me put a computed property in the Interface

Going to try converting to overload Method

Dave,

Have you used class interfaces in Xojo/RB/RS?

The answer could help us understand where you are hung up on understanding how to set this up.

  • Karen

[quote=175509:@Dave S]It won’t let me put a computed property in the Interface
[/quote]

You have to use methods to use a class interface

  • Karen

no

and it seems the the IDE crashes if you attempt to created an overloaded method in an interface

not here
You just need

name() as type
name(assigns v as type)

in the interface

now it behaves exactly like a property

Ok… 2014 crashs… 2015 doesn’t

The important thing is to use it you MUST cast to the INTERFACE as this is what gives you access to the functions the rest of the world WONT know about and CANNOT USE

the following is simply an outline of what you are trying to set up & a quick silly sample of how to use the two methods in the private interface

And FYI I’d say you should learn to use interfaces as they can be VERY useful

[code]
Module foo
private interface bar
baz() as integer
baz(assigns v as integer)
end interface

Class ClassB
      implements bar
           private function baz() as integer
           end function

           private function baz(assigns v as integer)
           end function

           public sub foo()
           end foo
end class

Class ClassA
      function getClassBList() as ClassB()
                return mClassBList
      end function

      sub changeSomeClassBProperty
             // since we know EVERY classB ISA BAR 
            // we can do this
           // and this gives us access to the private functions defined in the interface

             dim tmp as bar = mClassList(0)
             tmp.baz = tmp.baz() + 123 // <<<<<<< use the interface !
      end sub

      property mClassBList() as ClassB
end class

end module[/code]

Ok… got it… I Think :slight_smile:

Had to change the Computed Property in CLASS B to an OverLoaded Method
Then to keep the code simpler, I created a shadow overloaded method in Class A, the uses the Interface

At least it compiles, and runs… just need to see it it exposes what I want, and not what I don’t want :slight_smile:

Thanks everyone… I really do appreciate it… (today has been stressful… my poor puppy dog had cancer surgery today :frowning: )

PERFECT! works just the way I wanted…
and I learned something new… proving you CAN still teach an old dog new tricks (even if he does growl while doing so)