⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 oop.htm

📁 strongForth: a strongly typed dialect of Forth implemented in ANS Forth.
💻 HTM
📖 第 1 页 / 共 5 页
字号:
is a <em>friend</em> of another class can access its private and protected 
members, just as if these members were defined in the friend class itself. 
Within the definition of a class <kbd>A</kbd>, a list of classes 
<kbd>B1, B2, ..., Bn</kbd> can be granted access to the private and protected 
members of class <kbd>A</kbd> with the phrase:</p>
<pre>FRIENDS( class-B1 class-B2 ... class-Bn )</pre>
<p>Within each of the classes <kbd>B1, B2, ..., Bn</kbd>, you can then add 
the combined <kbd>PRIVATE</kbd> and <kbd>PROTECTED</kbd> word list of class 
<kbd>A</kbd> to the search order with the phrase</p>
<pre>ALSO ACCESS class-A</pre>
<p><kbd>ACCESS class-A</kbd> has a similar semantic like a vocabulary. 
<kbd>class-A</kbd>, <kbd>class-B1</kbd>, <kbd>class-B2</kbd>, ..., 
<kbd>class-Bn</kbd> are the actual class names. Note that only classes can be 
declared friends of a class. It is not possible, like in C++, to declare a 
word a friend to a class.</p>
<p>A typical application that takes advantage of the friendship mechanism is 
an iterator class. An iterator is a class that provides iterative access to 
some items that belong to another class. The iterator contains a member word 
that returns the <em>next</em> item of the other class each time it is 
executed. In the following example, 
an iterator is defined for a (simplified) <kbd>STRING</kbd> class. The member 
word <kbd>NEXT</kbd> of the iterator returns one character of the string after 
the other, starting with the first one:</p>
<pre>DT OBJECT PROCREATES STRING
DT OBJECT PROCREATES STRING-ITERATOR

CLASS STRING
BODY
  FRIENDS( STRING-ITERATOR )
  ALSO PROTECTED DEFINITIONS
  NULL UNSIGNED MEMBER LEN
  NULL CADDRESS -> CHARACTER MEMBER BUF
  ALSO FORTH DEFINITIONS PREVIOUS
  :MEMBER STRING ( CADDRESS -> CHARACTER UNSIGNED STRING -- 4 TH )
    >THIS DUP LEN ! CALLOCATE THROW -> CHARACTER BUF !
    BUF @ LEN @ MOVE THIS ;
  :MEMBER . ( STRING -- )
    >THIS THIS
    IF LEN @
       IF BUF @ LEN @ TYPE
       ELSE ." &lt;empty>"
       THEN
    ELSE ." &lt;null>" 
    THEN SPACE ;
  :MEMBER LENGTH ( STRING -- UNSIGNED )
    LEN @ ;
ENDCLASS

CLASS STRING-ITERATOR
BODY
  ALSO ACCESS STRING
  ALSO PROTECTED DEFINITIONS
  NULL STRING MEMBER STRI
  NULL UNSIGNED MEMBER INDX
  ALSO FORTH DEFINITIONS PREVIOUS
  :MEMBER STRING-ITERATOR ( STRING STRING-ITERATOR -- 2ND )
    >THIS STRI ! 0 INDX ! THIS ;
  :MEMBER NEXT ( STRING-ITERATOR -- CHARACTER )
    >THIS INDX @ STRI @ LENGTH &lt;
    IF STRI @ BUF @ INDX @ + @ 1 INDX +!
    ELSE NULL CHARACTER
    THEN ;
ENDCLASS</pre>
<p>Class <kbd>STRING-ITERATOR</kbd> is a friend of class <kbd>STRING</kbd>, 
because it needs access to <kbd>STRING</kbd>'s data members. Here's an example 
of how the two classes may be used together:</p>
<pre><u>" abc" NEW STRING CONSTANT STRING1</u>  OK
<u>" " NEW STRING CONSTANT STRING2</u>  OK
<u>STRING1 .</u> abc  OK
<u>STRING2 .</u> &lt;empty>  OK
<u>NULL STRING .</u> &lt;null>  OK
<u>STRING1 LENGTH .</u> 3  OK
<u>STRING2 LENGTH .</u> 0  OK
<u>STRING1 NEW STRING-ITERATOR CONSTANT SI1</u>  OK
<u>SI1 NEXT .</u> a OK
<u>SI1 NEXT .</u> b OK
<u>SI1 NEXT .</u> c OK
<u>SI1 NEXT CAST INTEGER .</u> 0  OK
<u>SI1 DELETE</u>  OK</pre>
<p>After the iterator has exceeded the end of the string, it is useless and 
can be deleted.</p>
<p>StrongForth does not allow class definitions to be nested. In the 
above example, the class definition of <kbd>STRING-ITERATOR</kbd> cannot be 
enclosed within the class definition of <kbd>STRING</kbd>, although this might 
look like a reasonable approach.</p>
<p>The class defnitions of <kbd>STRING</kbd> and <kbd>STRING-ITERATOR</kbd> 
contain, just like the last version of the class definition of <kbd>POINT</kbd>, 
only data members defined by <kbd>MEMBER</kbd> and <kbd>CMEMBER</kbd>, and 
member words defined by <kbd>:MEMBER</kbd>. But you've seen in the first version 
of <kbd>POINT</kbd>, that it is also possible to define member words as simple 
colon definitions. Now, what happens if you define words with <kbd>VARIABLE</kbd>, 
<kbd>CONSTANT</kbd>	 and <kbd>VALUE</kbd>? These words obviously define 
variables, constants and values that are not data members, and that are not 
even related to the class they are defined in. Nevertheless, it can make sense 
to use these defining words within a class definition, if they are added to 
the <kbd>PRIVATE</kbd> or <kbd>PROTECTED</kbd> word lists. Private variables, 
constants and values are only available to the members of the class and 
to friends of the class. and their names can be reused in other classes. The 
following extension of the <kbd>POINT</kbd> class contains both a private 
variable and a private constant:</p>
<pre>DT OBJECT PROCREATES POINT

CLASS POINT
BODY
  ALSO PRIVATE DEFINITIONS
  +0 MEMBER PX
  +0 MEMBER PY
  0 MEMBER PINDEX
  CHAR P CONSTANT ID
  0 VARIABLE COUNT
  ALSO FORTH DEFINITIONS PREVIOUS
  :MEMBER SET-POINT ( SIGNED SIGNED POINT -- )
    >THIS PY ! PX ! ;
  :MEMBER GET-POINT ( POINT -- SIGNED SIGNED )
    >THIS PX @ PY @ ;
  :MEMBER POINT ( POINT -- 1ST )
    >THIS +0 +0 SET-POINT 1 COUNT +! COUNT @ PINDEX ! THIS ;
  :MEMBER .NAME ( POINT -- )
    ID . PINDEX @ . ;
ENDCLASS</pre>
<p>Each object of class <kbd>POINT</kbd> is assigned an index <kbd>PINDEX</kbd>. 
In order to make sure that the index is unique, the index of a new 
<kbd>POINT</kbd> object is taken from a non-member variable <kbd>COUNT</kbd> 
that is incremented by the constructor. <kbd>.NAME</kbd> is a (public) 
member word that displays the index together with a one-letter identifier that 
is specific for points. The identifier is defined as a constant in the 
<kbd>PRIVATE</kbd> word list. Here's an example of how this version of 
<kbd>POINT</kbd> can be used:</p>
<pre><u>NEW POINT CONSTANT FIRST</u>  OK
<u>+3 -8 FIRST SET-POINT</u>  OK
<u>NEW POINT CONSTANT SECOND</u>  OK
<u>FIRST .NAME FIRST GET-POINT SWAP . .</u> P1 3 -8  OK
<u>SECOND .NAME</u> P2  OK</pre>
<p>Colon definitions defined by <kbd>:</kbd> can in some cases be used as a 
replacement for what is called in C++ a <em>static member</em> of the class, 
because they don't need to be bound to a specific object. The necessity to 
include those words in the class definition might arise from the fact that they 
access private or protected non-member variables, constants and values. If 
you need to overload colon definitions, you can add an object of the respective 
class type as a dummy input parameter. However, please note that such colon 
definitions within class definitions are actually not the same as static 
members in C++ classes.</p>
<p>Similarly, private constants in StrongForth must not be confused with 
<kbd>const</kbd> members in C++. It is not possible to reference a constant 
through an object of the class the constant is defined in. Furthermore, there is 
nothing like <kbd>const</kbd> classes or <kbd>const</kbd> member words that are 
not allowed to change the data members. Of course, you can define a class whose 
member words (except for the constructors) do not change the data members, but 
there are no means for the compiler to ensure that a class definition really does 
not contain non-constant member words.</p>
<h2>Inheritance And Binding</h2>
<p>The concept of inheritance is a fundamental technique of object oriented 
programming. You already got a quick glance at inheritance at the end of the 
section about structures. Generally, a class whose data type is a direct or 
indirect subtype of another class inherits the members from the other class. 
It's the same mechanism as for ordinary data types. For example, <kbd>DUP</kbd> 
is a word that expects an item of data type <kbd>SINGLE</kbd> on the stacks, 
but it can also be applied to all direct or indirect subtypes of 
<kbd>SINGLE</kbd>. So, let's design a simple class hierarchy that will serve 
as an example:</p>
<pre>DT OBJECT PROCREATES MEDIUM
DT MEDIUM PROCREATES PAPER-MEDIUM
DT MEDIUM PROCREATES ELECTRONIC-MEDIUM
DT PAPER-MEDIUM PROCREATES BOOK
DT PAPER-MEDIUM PROCREATES JOURNAL
DT ELECTRONIC-MEDIUM PROCREATES ANALOG-MEDIUM
DT ELECTRONIC-MEDIUM PROCREATES DIGITAL-MEDIUM
DT DIGITAL-MEDIUM PROCREATES CD
DT DIGITAL-MEDIUM PROCREATES DVD
\ ...</pre>
<p>Class <kbd>MEDIUM</kbd> is at the top of the class hierarchy. Each medium 
is supposed to have a title and a price. Here's the corresponding class 
definition:</p>
<pre>CLASS MEDIUM
BODY
  ALSO PROTECTED DEFINITIONS
  NULL STRING MEMBER TITLE
  NULL UNSIGNED MEMBER PRICE \ in cent
  FORTH DEFINITIONS PROTECTED
  :MEMBER MEDIUM ( CADDRESS -> CHARACTER UNSIGNED MEDIUM -- 4 TH )
    >THIS NEW STRING TITLE ! 0 PRICE ! THIS ;
  :MEMBER SET-PRICE ( UNSIGNED MEDIUM -- )
    PRICE ! ;
  :MEMBER GET-PRICE ( MEDIUM -- UNSIGNED )
    PRICE @ ;
  :MEMBER SALE ( MEDIUM -- )
    >THIS PRICE @ 8 10 */ PRICE ! ;
  :MEMBER .PRICE ( MEDIUM -- )
    PRICE @ 100 /MOD 0 .R [CHAR] . . S>D <# # # #> TYPE ;
  :MEMBER . ( MEDIUM -- )
    >THIS TITLE @ . ." ($" .PRICE ." )" ;
ENDCLASS
</pre>
<p>The data members are protected, whereas the member words including 
the constructors are public definitions that can be accessed from outside of 
the class definition. Remember that protected members can still be accessed 
within the definitions of derived classes.</p>
<p>Since data type <kbd>PAPER-MEDIUM</kbd> is a child of data type 
<kbd>MEDIUM</kbd>, it inherits all of <kbd>MEDIUM</kbd>'s data members and 
member words. Additionally, it defines the number of pages as a data member 
and a member word that returns the number of pages. Its constructor reuses 
the constructor of <kbd>MEDIUM</kbd> and additionally initializes the number 
of pages:</p>
<pre>CLASS PAPER-MEDIUM
BODY
  ALSO PROTECTED DEFINITIONS
  NULL UNSIGNED MEMBER #PAGES
  FORTH DEFINITIONS PROTECTED
  :MEMBER PAPER-MEDIUM ( CADDRESS -> CHARACTER UNSIGNED UNSIGNED 
       PAPER-MEDIUM -- 5 TH )
    >THIS #PAGES ! MEDIUM ;
  :MEMBER PAGES ( PAPER-MEDIUM -- UNSIGNED )
    #PAGES @ ;
  :MEMBER . ( PAPER-MEDIUM -- )
    DUP . CR PAGES . ." pages" ;
ENDCLASS</pre>
<p>Finally, here are the definitions of the <kbd>BOOK</kbd> and 
<kbd>JORUNAL</kbd> classes, which are both derived from 
<kbd>PAPER-MEDIUM</kbd>. The other classes (<kbd>ELECTRONIC-MEDIUM</kbd> and 
its derived classes) are not required for this example.</p>
<pre>CLASS BOOK
BODY
  ALSO PROTECTED DEFINITIONS
  NULL STRING MEMBER AUTHOR
  FORTH DEFINITIONS PROTECTED
  :MEMBER BOOK ( CADDRESS -> CHARACTER UNSIGNED UNSIGNED BOOK -- 5 TH )
    >THIS NULL STRING AUTHOR ! PAPER-MEDIUM ;
  :MEMBER SET-AUTHOR ( CADDRESS -> CHARACTER UNSIGNED BOOK -- )
    >THIS NEW STRING AUTHOR ! ;
  :MEMBER GET-AUTHOR ( BOOK -- STRING )
    AUTHOR @ ;
  :MEMBER . ( BOOK -- )
    DUP GET-AUTHOR . ." - " . ;
ENDCLASS

CLASS JOURNAL
BODY
  ALSO PROTECTED DEFINITIONS
  NULL UNSIGNED MEMBER YEAR
  NULL UNSIGNED MEMBER MONTH
  FORTH DEFINITIONS PROTECTED
  :MEMBER JOURNAL ( CADDRESS -> CHARACTER UNSIGNED UNSIGNED UNSIGNED 
       UNSIGNED JOURNAL -- 7 TH )
    >THIS YEAR ! MONTH ! PAPER-MEDIUM ;
  :MEMBER SALE ( JOURNAL -- )
    100 SWAP PRICE ! ;
  :MEMBER .EDITION ( JOURNAL -- )
    DUP MONTH @ 0 .R [CHAR] / . YEAR @ . ;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -