home *** CD-ROM | disk | FTP | other *** search
- /*
- heritest.prg
-
- 21/03/1991 21:18 avs - updated
- 26/05/1991 07:36 avs - updated
-
- This program demonstrates many of the inheritance and scoping features
- of Class(y), as well as some of the more advanced features. The
- program displays a menu of options; many of which will generate an
- error when selected. In these cases, an illegal operation has
- deliberately been performed.
-
- NOTE: The output from this program is not very informative in itself.
- We suggest that you trace through the program in the Clipper debugger,
- and examine variable values as necessary.
-
- The program uses a box class, defined in HTBOX.PRG, which is inherited
- from the rectangle class defined in this module. The rectangle class is
- very limited, and is not the same one used in the manual.
- */
-
- #include "class(y).ch"
-
-
- procedure main
- local i, ivar, oBox, tStart
- local BoxClass
- local opt := 1
-
- cls
- oBox := Box():new(2, 5, 16, 24, "╔═╗║╝═╚║ ", "R+/W", "RB+/BG")
-
- while opt <> 0
- @ 2, 12 say 'Errors'
- @ 3, 6 prompt ' Private access '
- @ 4, 6 prompt ' Protected access '
- @ 5, 6 prompt ' Bad assignment '
- @ 6, 6 prompt ' Msg -> non-obj '
- @ 7, 6 prompt ' Bad message '
- @ 8, 6 prompt ' Access via class '
- @ 9, 6 say '──────Tests───────'
- @ 10, 6 prompt ' Self in block '
- @ 11, 6 prompt ' Scalar classes '
- @ 12, 6 prompt ' Superclass name '
- @ 13, 6 prompt ' Class scope msgs '
- @ 14, 6 prompt ' Class variables '
- @ 15, 6 prompt ' Class objects '
- menu to opt
- set color to 'W/N'
- @ 20, 0
- do case
- /*
- The following six options test variable scoping features
- and so forth, and all intentionally cause an error.
- */
- case opt == 1
- // illegal access of a private instance variable
- ? oBox:boxChars
- case opt == 2
- // illegal access of a protected instance variable
- ? oBox:boxType
-
- case opt == 3
- // illegal assignment to read-only variable
- oBox:top := 42
- case opt == 4
- // sending a message to a non-object
- ? opt:boxChars
- case opt == 5
- // sending an unknown message to an object
- ? oBox:volume
- case opt == 6
- // attempting to access an _instance_ variable via the
- // class function ie. without using an object of that class.
- ? box():top
- /*
- The following options demonstrate and test various
- Class(y) features. These should not cause errors.
- */
- case opt == 7
- // Accessing the 'self' variable within a code block
- // (see the 'testBlock' method)
- oBox:testBlock()
- case opt == 8
- // Sending messages to the 'scalar' types such as numeric,
- // character etc (see the 'scalarClasses()' function).
- scalarClasses()
- case opt == 9
- // Explicitly accessing an object's superclass with the
- // 'super' message. In this case, we print the name of
- // the superclass using the 'className' message.
- ? "Using :super to access the name of an object's superclass"
- ? 'oBox:super:className -', oBox:super:className
- case opt == 10
- // Another test of the 'super' message, comparing it with
- // using a specific class name ('rectangle') to specify
- // where to begin a message search.
-
- ? 'See HERITEST.PRG for explanation'
- // First invoke method 'test' in class Box
- oBox:test()
- // Now invoke the same method in the Box's superclass, which
- // in this example is Rectangle. Use the 'super' message.
- oBox:super:test()
- // Invoke it in Box again, to check that nothing is 'stuck'
- oBox:test()
- // invoke in class Rectangle by naming the class explicitly
- oBox:rectangle:test()
- // and Box again, as a final check
- oBox:test()
- case opt == 11
- // Test class variables, which apply to an entire class rather
- // than to an individual object, or instance of the class.
- // First access class variables via an object.
- oBox:nRects := 42
- oBox:nBoxes := 23
- ? 'Accessing :nRects and :nBoxes via the oBox object:'
- ? oBox:nRects, oBox:nBoxes
- // Now access them via the 'class functions'. Note that the
- // same values are printed, since they are the same variables.
- ? 'Do the same use the Box() class function:'
- ? Box():nRects, Box():nBoxes
- ? 'And access :nRects via the Rectangle() class function:'
- ? Rectangle():nRects
- case opt == 12
- // Use the predefined 'class' message to obtain an object's
- // 'class object'. A class object contains any class variables
- // that a class has.
- BoxClass := oBox:class
- ? 'Access class variables via a class object:'
- ? BoxClass:nBoxes
- // The class function also returns a class object. We can
- // check that these are the same as follows:
- ? 'Check that class object is same as returned by class function:'
- ? (BoxClass == Box())
- end
- if opt <> 0
- wait
- cls
- oBox:draw()
- end
- end
- return
-
-
- /*
- Using Class(y), the scalar types (eg. NUMERIC, DATE etc) accept the
- CLASSNAME and CLASSH messages, as they do in standard Clipper 5.01. In
- all object classes, 'classH' returns a number identifying the class.
- This can be used to test whether two objects belong to the same class,
- for example. The built in data types all respond to the 'classH'
- message with zero.
- */
-
- static procedure scalarClasses
- local i
- // set up an array of the simple types: code block, nil, numeric, logical, character, array, date
- local aTypes := { { || qout("wow") }, nil, 2, .t., "wow", array(4), date() }
-
- ? 'Simple (scalar) variable type response to standard messages'
- ?
- ? ' classH valtype() className'
- for i := 1 to len(aTypes)
- ? aTypes[i]:classH, ' ', valtype(aTypes[i]), ' ', aTypes[i]:className
- next
- return
-
-
- /*
- Here we define the Rectangle class
- */
-
- create class Rectangle
-
- export:
- classvar nRects
-
- instvar top, left, bottom, right readonly
- instvar width, height readonly
-
- method set
- method test
- method testBlock
-
- endclass
-
-
- constructor new (nTop, nLeft, nBottom, nRight)
- ::set(nTop, nLeft, nBottom, nRight)
- return
-
-
- method procedure set(nTop, nLeft, nBottom, nRight)
- ::top := nTop
- ::left := nLeft
- ::bottom := nBottom
- ::right := nRight
-
- ::width := nBottom - nTop
- ::height := nRight - nLeft
- return
-
-
- method procedure test
- // print a message to indicate which method is executing
- ? 'Executing Rectangle:test'
- return
-
-
- /*
- :testBlock
-
- Test the accessing of an instance variable within a code block.
- */
-
- method procedure testBlock
- local b := { || ::top }
- ? 'Accessing an instance variable within a code block:'
- ? 'self:top =', eval(b)
- return
-
-
- // eof heritest.prg
-