Τρίτη, 10 Οκτωβρίου 2017

M2000: Using classes derived from other class

In this example, we have a group (object in M2000) constructor without using class name {}. A global lambda function serve as a class function. A lambda function can capture variables, and these variables are copies inside lambda. So every time we use the account() function we get a new id for account.
But we want another object, the savingsaccount, subclassing the account class. Because M2000 use no interfaces, we have to merge account object to savingaccount object. Also we want a new printdata to replace the account's printdata. Because we want to construct savingsaccount after we get an account, we done the construct in construction module, making a temporary group as m, and adding using group m{ } the new fields/modules.
A class: label defines the part which is valid (or we say exist) only until we get a copy of a group, and that happen in any class or function that convert a named group to a non named (a floating group).

A group may exist with name in a module or in a function when module or function run. Here we can make some named groups to exist only in a block For This {}. We can make these groups as floating groups when we write them in array items.
Statement a=(k,z, n, m)  defines a pointer to an array of four items. These items are copied of k, z, n, m as float groups. The (,) means empty array, and (0,) means one item array. We can make arrays to arrays using this "auto array" assignment like ((1,2),(3,4)) which defines two arrays in a two items array.
Also pointer to object like a, can used in Each() iterator, a special object which holds a cursor and a pointer to object. Each() iterator works for arrays, inventories (lists), and stack objects. We can set range, using numbers (-1 is the last item, -2 is second from last), or using names Start and End. Using numbers we have to use coma to separate numbers, but using names we have to use no coma but a To between first and last item: a1=each(a end to start). Sometimes we prefer to use a1^ as an index (cursor) or a1 as object using index internal. While a1 {} is a structure which advance the cursor.

Statement Link a to a() make an array a() as reference to a. Both a and a() points to same array, but they are different interfaces.

Arrays in M2000 have a variant type for each item, and we can put any object, including arrays too.
We can define property in a group (it is a group in a group). Here we define id as property, which is read only (setting only value). There is a private .[id] variable which we can set value to id. So inside a group module or function we can alter id value, but not outside.

When we call a function, there is no check for kind or number of items we pass to, and at the exit the internal stack erased. So it is function's responsibility to check and perhaps to read the stack. When in a function definition put next to name a parameter (or more than one) in parenthesis, interpreter insert a new line in final code, a Read statement. If we prefer we can make this job manual, so we can make special Read, as we see in account(), using ? for optional reading parameters. Properties may have value, or set, or both, or special defined value, and or set functions. Also we can define modules, functions, fields, and other properties. If a property has a string value, then we have to defined with a name with $ at the end, but exist the same name without $, for working for calling/using modules, functions etc.
Statement a(4)=a(0).copy_account(100) perform nice tasks. First open a(0) and call copy_account which get 100 money units and pack then in an account group. This group copied to a(4) (in fact only the pointer to group copied). So after this statement, a(0) has less 100 money units and that money transfer to a new account, a(4) which take a new id number 5.


We can place one or more =expression in a function. We get exit from function at the end of code, or with Exit, or with Break command, but not with =expression. Look copy_account() function


\\ define a global lambda function
\\ using internal c1 as static variable
\\ also can get optional one parameter (deposit)
global account =lambda c1=0-> {
           c1++
           Read ? deposit
           group m {
                        Private:
                              balance=deposit, counter=c1
                        Public:
                              property id {value}=c1
                              function copy_account (money) {
                                   if money<=.balance and money>0 then {
                                          .balance-=money
                                          =account(money)
                                    } else =account()
                              }
                              module Deposit (money){
                                    .balance+=money
                              }
                              module printdata {
                                    print "account id:"; .id
                                    print "bankaccount"
                                    print "balance=";.balance
                              }                  
                        }
                        =m
}
class savingsaccount {
class:
      module savingsaccount (m, m_ratio) {
            group m {
            private:
                  ratio=m_ratio
            public:
                        module printdata {
                              print "account id:"; .id
                              print "savingaccount"
                              print "balance=";.balance; " ratio=";.ratio
                        }
            }
            This=m
      }
}
a=(,)
For this {
      \\ k, z, n are for temporary use
      k=savingsaccount(account(100), 0.2)
      z=savingsaccount(account(200), 0.3)
      k.deposit 200
      n=account(1000)
      m=account(500)
      a=(k,z, n, m)
}
link a to a()
dim a(7) \\ add three more items to a
a(4)=a(0).copy_account(100) \\ a simple acount
a(5)=savingsaccount(a(0).copy_account(100),0.1)
a(6)=account(2000)
a1=each(a)
while a1 {
      \\ using a1^ as index
       a(a1^).printdata
}
list
Print "Press any key"
a$=key$
a1=each(a end to start)
while a1 {
      for this {
            \\ block for temporary definitions
            m=array(a1)
            m.printdata
      }
}