make a private property in classA named “myclassB” and type ClassB
make a constructor to assign the classB to the classA
refer to the classB with the property myClassB from classA
If we tried to do that, we never get anything done… They should have no knowledge of or reliance on how the other class has been implemented.
So the first thing to sort out: Are you talking about a property of the class or a property of an instance of a class?
If you are referring to a property of the class, then the class must exist, otherwise wise it will not fly.
If you are referring to a property of an instance of class B, then the instance of class A must in some why receive a reference to the instance of class B, either in it’s constructor or as a parameter to a method call on the instance.
In order to handle the fact that the class has not been defined, you need to introduce an interface into the equation, so class A would then interact with the interface rather than class b. Later when you come to create class b, you need to have it implement the interface so it can interact with class A.
@Alexander van der Linden Classes cannot be agnostic of each others. If your class A uses class B, then it has to know how to use it and A becomes dependent on B. That is perfectly normal.
[quote=444005:@Alexander van der Linden]I’m developing a class (ClassA) which behavior will be influenced by another class (ClassB).
Somewhere in a method of ClassA I have to write:
If ClassB.Property1 = False then
do this
else
do that
end if
But ClassA doesn’t now how ClassB will be implemented. Moreover, I was always taught that classes should be agnostic of each other. How to solve this?[/quote]
Use an interface
Then have classB implment that interface
An interface is quite literally a contract about how a class will behave but NOT about its implementation of that behaviour
ClassA then has a property that refers to an instance that IS the interface type and you have some API for setting that
Then your code is more like
If ClassB.ShouldDoThat = False then
do this
else
do that
end if
and you’re not reaching into the guts of the implementation (ie reading a property)
It’s a property of an instance of that class. That’s why it doesn’t know what it’s name will be. I haven’t yet worked with interfaces or constructors yet. I could reach my goals perfectly without it.
Interfaces are really simple
Basically when you say a class implements an interface what you are promising is that the class will implement all of the methods of the interface - it can implement others as well but they arent part of the agreed to “contract”
It makes it so that you can swap the actual instance out for a different one as long as they both implement the interface
For instance, suppose you have a bunch of classes that are unrelated so a class hierarchy makes no sense. Maybe there is a class for a Car, and a Horse. A car is not a horse and the horse is not a car so its unlikely they have any relationship in their super classes.
But, both can MOVE. How they move is different.
So they might both implement a “Movable” interface which has one method - Move(inDirection as integer)
We can debate about direction as an integer - but accept that this means “move in a given direction”
So we have
Interface Movable
Sub Move(inDirection as integer)
End Interface
And then we make Car implement Movable
Class Car
Implements Movable
Sub Move(inDirection as integer)
// in here we write the code for how to move a car
End Sub
.... // other methods & properties of a Car
End Class
And Horse implement Movable
Class Horse
Implements Movable
Sub Move(inDirection as integer)
// in here we write the code for how to move a horse
End Sub
.... // other methods & properties of a Horse
End Class
Now anything that knows how to tell a Movable to move can use either a car or a horse and really doesnt care which it is
It knows its “Movable”
dim m as Movable
m = new Car
m.move(129)
m = new Horse
m.move(129)
And since an interface IS a new type you can also do things like ISA tests
dim v as Variant
v = new Car
if v isa Movable then
Movable(v).move(129)
end if
thanks. I thinks I grasp the basics. But this is about methods. What I want to share between classes is the outcome of a calculation which is stored in a property in class Horse but is needed in class Car. But class Car doesn’t know if class Horse is implemented as MyHorse of MrEd and I tried already but either way it won’t compile.
make the method in the interface a FUNCTION that returns a value
you still need some reference to the class - whether that is saved as a property in the class relying on the other one or not
suppose Movable includes a “DistanceMoved() as Integer” function
then any things that knows about “movable” can also find out how far the thing moved when told to move
dim m as Movable
m = new Car
m.move(129)
if m.DistanceMoved() < 100 then
/// .... etc
end if
m = new Horse
m.move(129)
if m.DistanceMoved() < 100 then
// etc .....
end if
[quote=444097:@Norman Palardy]make the method in the interface a FUNCTION that returns a value
you still need some reference to the class - whether that is saved as a property in the class relying on the other one or not
suppose Movable includes a “DistanceMoved() as Integer” function
then any things that knows about “movable” can also find out how far the thing moved when told to move
dim m as Movable
m = new Car
m.move(129)
if m.DistanceMoved() < 100 then
/// .... etc
end if
m = new Horse
m.move(129)
if m.DistanceMoved() < 100 then
// etc .....
end if
Same for your case[/quote]
Works! Thanks
Another question: I have a Canvas subclass in which I already use the Paint event to draw a specific pattern. But I want the Paint event to be available for the user as well. So I added an event definition ‘Paint’ and in the Paint event I do my drawing and I tried to use
Return RaiseEvent Paint(g as Graphics, areas() as REALbasic.rect)
but that won’t compile. How to use the Paint event and make it available again?
Event Paint(g as Graphics, Areas() as REALbasic.Rect) As Graphics
Sub Paint(g As Graphics, areas() As REALbasic.Rect) Handles Paint
G.ForeColor = Me.GridColor
For I As Integer = 1 To Me.Width Step (Me.BlockSize + Me.GridSize)
For J As Integer = 1 To Me.Height Step (Me.BlockSize + Me.GridSize)
G.FillRect(I,J,Me.Blocksize,Me.Blocksize)
Next
Next
Return RaiseEvent Paint(g,areas)
End Sub
Compiler error: PlayCanvas.Paint, line 10
You cannot return a value because this method has not defined a return type
Return RaiseEvent Paint(g,areas)
the error tells you exactly whats wrong
the paint event you ADDED can return a value but the PAINT event you implemented in the class cannot RETURN a value