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.
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
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'll have to wait till Paul has time to explain the why's and wherefore's further.
I can't.
Larry
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.
Bob,
You showed him the samething I did ;)
At least I know I was right now.
:D
Larry
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 (http://www.artima.com/objectsandjava/webuscript/CompoInherit1.html)
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?
:)
Just look here, Bob.
http://www.artima.com/objectsandjava/ (http://www.artima.com/objectsandjava/)
Here is another one.
http://java.sun.com/docs/books/tutorial/java/index.html (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/ (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) (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.