March 28, 2024, 07:48:27 AM

News:

Own IWBasic 2.x ? -----> Get your free upgrade to 3.x now.........


Class 2 as instance variable of Class 1?

Started by danbaron, December 03, 2009, 09:10:21 PM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

danbaron

December 03, 2009, 09:10:21 PM Last Edit: December 03, 2009, 09:48:32 PM by danbaron
Hello fellow humanoids.

In the code shown below, I have two classes, CLASSONE, and CLASSTWO.

This program runs as I hoped it would, printing "6" to the console.

CLASS CLASSTWO
PUBLIC
INT TWOVAR
DECLARE TWOSUB()
ENDCLASS

SUB CLASSTWO::TWOSUB()
PRINT "HELLO"
ENDSUB

CLASS CLASSONE
PUBLIC
CLASSTWO TWOINSTANCE
ENDCLASS

INT I
CLASSONE ONEINSTANCE
ONEINSTANCE.TWOINSTANCE.TWOVAR = 6
PRINT ONEINSTANCE.TWOINSTANCE.TWOVAR
/*ONEINSTANCE.TWOINSTANCE.TWOSUB()*/
INPUT I
END


But, when I un-comment the line, "/*ONEINSTANCE.TWOINSTANCE.TWOSUB()*/", the program won't run.
I get the error message, "undefined variable" for that line.

So, it seems that when I make CLASSTWO an instance variable of CLASSONE, I can access the
instance variables of CLASSTWO, but I cannot access the subroutines of CLASSTWO.

Is there a way to access the subroutines of CLASSTWO from CLASSONE?

I would like to be able to wrap the instantiations of a number of utility classes inside one driver class.

Thanks.
DTB.
"You can't cheat an honest man. Never give a sucker an even break, or smarten up a chump."  -  W.C. Fields

LarryMc

December 03, 2009, 10:50:06 PM #1 Last Edit: December 03, 2009, 10:56:38 PM by Larry McCaughn
CLASS CLASSTWO
PUBLIC
INT TWOVAR
DECLARE TWOSUB()
ENDCLASS

SUB CLASSTWO::TWOSUB()
PRINT "HELLO"
ENDSUB

CLASS CLASSONE, CLASSTWO
PUBLIC
DECLARE ONESUB()
ENDCLASS

SUB CLASSONE::ONESUB()
print
Print "Any key to end"
ENDSUB


CLASSONE ONEINSTANCE

ONEINSTANCE.TWOVAR = 6
PRINT ONEINSTANCE.TWOVAR
ONEINSTANCE.TWOSUB()
ONEINSTANCE.ONESUB()

waitcon
END


It's covered in the Help file under Language/Object Oriented Programming then scroll down to the Inheritance paragraph.

Larry
LarryMc
Larry McCaughn :)
Author of IWB+, Custom Button Designer library, Custom Chart Designer library, Snippet Manager, IWGrid control library, LM_Image control library

danbaron

December 04, 2009, 11:07:04 PM #2 Last Edit: December 05, 2009, 12:18:29 AM by danbaron
My understanding is that inheritance is used when the child class has a "is a"
relationship with the parent class. For instance, a lion is a cat. So, it would
be sensible to have a lion class inherit from a cat class. What I would like to
do is instantiate a number of utility classes from inside a driver class. That
way, the user would only have to interact with the driver class, and would not
even need to be aware of the utility classes. The utility classes may not have
anything in common with each other, and certainly would not have anything in
common with the driver class.

EB supports single inheritance. I don't think it will do me any good to have all
of the utility classes inherit from the driver class. I don't think an
instantiation of the driver class would have access to the contents of the
utility classes. Instead, I think instantiations of the utility classes would
have access to the contents of the driver class.

Let's say, my driver class is "D". And I have 5 utility classes, "E-I". I
suppose, to connect all of these classes using single inheritance, I could have
H inherit from "I", G inherit from H, F inherit from G, E inherit from F, and D
inherit from E. Then, I guess, Class D would have the functionality of all of
the utility classes, E-I. However, since the utility classes are functionally
independent of each other, and I don't want any overriding of class variables or
subroutines, I would need to make sure that none of the classes used the
same variable or subroutine names. In that case, I might just as well put the
driver class, and all 5 utility classes into one giant class.

A class can have a UDT as an instance variable. Logically, it seems to me that a
class should also be able to have a class as an instance variable. Additionally,
as the program in my first post showed, if I code Class A to have Class B as an
instance variable, then, when I instantiate Class A, I can access the variables
of Class B, but I cannot access the subroutines of Class B. That seems
inconsistent to me.

I'm no expert on design patterns, but instead of the "is a" relationship of
inheritance, I think I want a "has a" relationship. For instance, say I am
making a robot class. A robot has a head. So, the robot class might contain
(instantiate) a head class. A head has a mouth. So the head class might contain
a mouth class. Then, potentially, I could execute the statement,
"robot.head.mouth.open()".

Dan.
"You can't cheat an honest man. Never give a sucker an even break, or smarten up a chump."  -  W.C. Fields

LarryMc

December 04, 2009, 11:52:23 PM #3 Last Edit: December 05, 2009, 07:40:13 PM by Larry McCaughn
You'll have to wait till Paul has time to explain the why's and wherefore's further.
I can't.

Larry
LarryMc
Larry McCaughn :)
Author of IWB+, Custom Button Designer library, Custom Chart Designer library, Snippet Manager, IWGrid control library, LM_Image control library

REDEBOLT

December 05, 2009, 10:37:13 AM #4 Last Edit: December 05, 2009, 10:50:15 AM by REDEBOLT
Maybe I'm wrong, but I think CLASSONE must inherit from CLASSTWO if it is to use
CLASSTWO's members and methods.  Try the following:

CLASS CLASSTWO
PUBLIC
INT TWOVAR
DECLARE TWOSUB()
ENDCLASS

SUB CLASSTWO::TWOSUB()
PRINT "HELLO"
ENDSUB

CLASS CLASSONE,CLASSTWO
'PUBLIC
'CLASSTWO TWOINSTANCE
ENDCLASS

INT I
CLASSONE ONEINSTANCE
'ONEINSTANCE.TWOINSTANCE.TWOVAR = 6
'PRINT ONEINSTANCE.TWOINSTANCE.TWOVAR
ONEINSTANCE.TWOVAR = 6
PRINT ONEINSTANCE.TWOVAR
ONEINSTANCE.TWOSUB()
WAITCON
END


This works since CLASSONE "knows" CLASSTWO's members and methods.
Regards,
Bob

LarryMc

Bob,
You showed him the samething I did ;)

At least I know I was right now.
:D
Larry
LarryMc
Larry McCaughn :)
Author of IWB+, Custom Button Designer library, Custom Chart Designer library, Snippet Manager, IWGrid control library, LM_Image control library

danbaron

December 06, 2009, 02:16:53 AM #6 Last Edit: December 06, 2009, 02:33:00 AM by danbaron
In OOP, "composition" is the term used to describe the structure, in which a class contains instances of other classes.
Here is a link to a page that demonstrates both composition and inheritance, in Java.

DTB.

http://www.artima.com/objectsandjava/webuscript/CompoInherit1.html
"You can't cheat an honest man. Never give a sucker an even break, or smarten up a chump."  -  W.C. Fields

REDEBOLT

Dan,

Thanks for the link. It is very well written.
Do you hace a link to the other chapters?
I tried the link labelled "Chapters" but couldn't
find any relevant material.

Have you looked at Scala?"
It looks interesting.
Do you know where I can get a compiler for it?

:)
Regards,
Bob

danbaron

December 08, 2009, 02:14:46 AM #8 Last Edit: December 08, 2009, 11:33:08 AM by danbaron
Just look here, Bob.
http://www.artima.com/objectsandjava/

Here is another one.
http://java.sun.com/docs/books/tutorial/java/index.html

Here is the Scala site.
You can download it from there.
http://www.scala-lang.org/

I have read a little about Scala, but that's all.
I have the impression that it is intended to be the successor to Java.
Look here.
http://en.wikipedia.org/wiki/Scala_(programming_language)

But, back to inheritance and composition. You can see that inheritance is used
for the cases in which there is an "is a" relationship between the classes. The
base class implements the most general functionality. As the family tree is
extended, each new generation implements more specific functionality. For instance,
an integer is a number. A prime, is an integer. A Mersenne, is a prime. So, it
would make sense to have the integer class inherit from the number class, the
prime class to inherit from the integer class, and the Mersenne class to inherit
from the prime class. The idea of inheritance is to save you work. If you
already have the number class, then you can inherit from it to make the integer
class. Presumably, this will be less work than writing the entire integer class
from the beginning. If you made the number hierarchy, then you could instantiate
the Mersenne class by the statement

mersenne mp

Inheritance is not natural for the cases in which the relationships between the
classes is "has a". Then, composition is used. For instance, a document has
paragraphs. A paragraph has sentences. A sentence has words. A word has
characters. So, it would make sense to have the document class contain an
instance of the paragraph class, the paragraph class to contain an instance of
the sentence class, the sentence class to contain an instance of the word class,
and the word class to contain an instance of the character class. Composition
can hide the classes that the user doesn't need to interact with. It also makes
the program logic clearer to the programmer. For the document class, the methods
that the user needs to make a document, could be public, but the classes
contained within the document class, could be private.

Within the document class, you could have
PRIVATE
paragraph par

Within the paragraph class, you could have
PRIVATE
sentence sen

Within the sentence class, you could have
PRIVATE
word wrd

Within the word class, you could have
PRIVATE
character chr

You could create an instance of the document class by the statement

document doc

Say, the document class has a public method makedocument()

You would invoke it by

doc.makedocument()

makedocument() might look something like this

sub document::makedocument()
while something
par.makeparagraph()
endwhile
endsub

makeparagraph() might look something like this

sub paragraph::makeparagraph()
while something
sen.makesentence()
endwhile
endsub

makesentence() might look something like this

sub sentence::makesentence()
while something
wrd.makeword()
endwhile
endsub

makeword() might look something like this

sub word::makeword()
while something
chr.getchar()
endwhile
endsub

The user only needs to interact with the public methods of the document class.
And they are the only methods that he can interact with (because of the PRIVATE
designations). He cannot access the nested classes and their methods. For
instance, he would be prevented from executing the statement

doc.par.makeparagraph()

On the other hand, if above, PUBLIC had been used instead of PRIVATE, then the
user would be able to execute the statement

doc.par.sen.wrd.chr.getchar()

Dan.
"You can't cheat an honest man. Never give a sucker an even break, or smarten up a chump."  -  W.C. Fields