# Class ## Function class is used to encapsulate a set of fields and methods into the same object structure. Fields save instance status, methods describe instance behavior, and `this` is used internally to access the current instance. BT's class syntax follows a JavaScript-like style, but constructs instances with `ClassName::constructor(...)`. The most common constructor name is `new`, so this is usually written as `User::new(...)`. ## Syntax ### Define class ```text class ClassName { field_name: initial_value field_name pub public_field: initial_value method_name(parameter1, parameter2) { method_body } pub public_method(parameter) { method_body } new(parameter) { initialization_logic this } } ``` ### Create instance ```text object = ClassName::new(parameter) object = ClassName::other_public_constructor(parameter) ``` `Class::new()` is the current instantiation writing method of BT, not `new Class()`. ## Members class members are divided into fields and methods. The Fields use `name: expression` declarations: ```bt class User { name: 'Unnamed' age: 0 } ``` ### Naked field The field can also only write the name without writing `:` and initial value. This writing method is called a naked field. The naked field will occupy a member name in the instance in advance, and the default value is `empty`. ```bt class User { name new(name) { this.name = name this } pub get_name() { this.name } } user = User::new('Tom') println user.get_name() ``` The naked fields `name` and `name: ''` are different: the default value of `name` is `empty`, and the default value of `name: ''` is the empty string. `this.name = name` is usually used in the constructor to override the default value. The Methods do not use `fn`; write `method_name(parameters) { ... }` directly: ```bt class User { name: 'BT' pub get_name() { this.name } } ``` method has the same return value as an ordinary function. When there is no explicit `return`, the value of the last statement in the method body is the return value. ## this `this` represents the currently operating instance and is only used in class methods and constructors. ```bt class Counter { value: 0 pub inc() { this.value++ this } pub get() { this.value } } counter = Counter::new() counter.inc().inc() println counter.get() ``` `this.value` is used to read the current instance fields, `this.value = 1` is used to write the current instance fields, and `this.method()` is used to call other methods of the current instance. Access to private members must be done directly through `this.xxx`. Do not assign `this` to other variables before accessing private members, because permission judgment only regards access directly from `this` as class internal access. ```bt class User { password: '' new(password) { this.password = password this } check(password) { this.password == password } pub login(password) { this.check(password) } } ``` ## new `new` is the most common constructor name. Write `ClassName::new(...)` when creating an instance. ```bt class User { name: '' age: 0 new(name, age) { this.name = name this.age = age this } pub info() { this.name + ':' + this.age } } user = User::new('Tom', 18) println user.info() ``` If `new` is not defined in the class, `Class::new()` will still create an instance and use the default value in the class field: ```bt class Config { pub host: '127.0.0.1' pub port: 8080 } config = Config::new() println config.host println config.port ``` The constructor return rule requires special attention: the BT method returns the value of the last statement by default. After the constructor is executed, if `empty` or `null` is returned, `Class::new()` will return a new instance; if another value is returned, that value will be returned. Therefore, it is recommended to write `this` in the last line of the constructor to clearly return the current instance: ```bt class User { name: '' new(name) { this.name = name this } } ``` Don't just put the assignment statement in the last line of the constructor: ```bt class User { name: '' new(name) { this.name = name } } user = User::new('Tom') ``` The last statement of `new` above is an assignment expression, and the assignment expression returns `'Tom'` on the right, so `User::new('Tom')` returns a string, not an instance. ## Multiple structure entries BT constructors are not limited to `new`. Any public method can be used as a construction entry through `ClassName::method_name(...)`: the runtime first creates an instance, then binds `this` to it while executing that method. ```bt class User { name: '' role: 'user' new(name) { this.name = name this } pub admin(name) { this.name = name this.role = 'admin' this } pub label() { this.name + ':' + this.role } } tom = User::new('Tom') root = User::admin('Root') println tom.label() println root.label() ``` Except for `new`, the method used as the entrance to the construction needs to be `pub`, otherwise it cannot be accessed outside the class. ## Public and private class members are private by default. Only fields or methods added with `pub` can be accessed through instances outside the class. ```bt class Account { balance: 0 new(balance) { this.balance = balance this } pub deposit(amount) { this.balance += amount this } pub get_balance() { this.balance } can_withdraw(amount) { this.balance >= amount } pub withdraw(amount) { if this.can_withdraw(amount) { this.balance -= amount true } else { false } } } account = Account::new(100) account.deposit(50) println account.get_balance() println account.withdraw(80) println account.get_balance() ``` Externally accessible: ```bt account.deposit(50) account.get_balance() ``` Externally not accessible: ```bt account.balance account.can_withdraw(10) ``` Private members are still accessible inside the class via `this`: ```bt this.balance this.can_withdraw(10) ``` BT currently does not have the `private` keyword. The default is private, write `pub` only when it needs to be made public. ## Field writing Public fields can be read and written outside the class: ```bt class User { pub name: '' } user = User::new() user.name = 'Tom' println user.name ``` Private fields can only be written inside the class through `this`: ```bt class User { name: '' pub set_name(name) { this.name = name this } pub get_name() { this.name } } ``` If a field that has not been declared in the class definition is added to `this`, this field will be saved as a private field; if a field is added on an external instance, this field will be saved as a public field. ```bt class User { pub set_token(token) { this.token = token this } } user = User::new() user.set_token('abc') user.nickname = 'Tom' ``` The above `token` is a private field added through `this` inside the class, and `nickname` is a public field added externally. ## Chain call BT supports chain call. If the class method wants to continue the chain call, just return `this`. ```bt class Query { table: '' where_sql: '' limit_size: 0 new(table) { this.table = table this } pub where(sql) { this.where_sql = sql this } pub limit(size) { this.limit_size = size this } pub sql() { 'select * from ' + this.table + ' where ' + this.where_sql + ' limit ' + this.limit_size } } sql = Query::new('users') .where('age >= 18') .limit(10) .sql() println sql ``` ## Parameters class itself has no calling parameters. Parameters are written on the constructor or ordinary method. ```bt class Page { page: 1 size: 20 new(page = 1, size = 20) { this.page = page this.size = size this } } p1 = Page::new() p2 = Page::new(2, 50) ``` ## Return Value - `class Name { ... }` will create a class value and save it to the class name variable. - `Name::new(...)` returns a class instance by default. - `Name::method(...)` will first create a class instance, and then execute the specified method as the construction entry. - The instance method returns the value of the last statement in the method body, or you can use `return` to force the return. - The constructor call returns a new instance when the constructor method returns `empty` or `null`; it returns that value when another value is returned. ## Code Examples ### Complete encapsulation example ```bt class User { name: '' password: '' pub role: 'user' new(name, password) { this.name = name this.password = password this } pub admin(name, password) { this.name = name this.password = password this.role = 'admin' this } pub get_name() { this.name } pub rename(name) { this.name = name this } check_password(password) { this.password == password } pub login(password) { this.check_password(password) } pub label() { this.name + '[' + this.role + ']' } } user = User::new('Tom', '123456') admin = User::admin('Root', 'root_pwd') println user.rename('Tommy').label() println user.login('123456') println admin.label() ``` ### Private member protection status ```bt class Counter { value: 0 new(start = 0) { this.value = start this } pub inc() { this.value++ this } pub dec() { this.value-- this } pub get() { this.value } } counter = Counter::new(10) counter.inc().inc().dec() println counter.get() ``` ## Notes - `Class::new()` is instantiation syntax; do not write `new Class()`. - `new` is the recommended constructor name; if `new` is not defined, `Class::new()` will also return an instance with default fields. - It is recommended to write `this` in the last line of the construction method to prevent the last assignment statement from returning ordinary values such as strings and numbers as the construction result. - Members are private by default; public fields or methods must be written as `pub`. - Private members can only be accessed inside the class via `this.xxx`. - There is currently no `private`, `extends`, `super`, `static` syntax; do not use it according to the JS class inheritance writing method. - Field initial values are suitable for scalar default values; variable values such as arrays and objects are recommended to be initialized with `this.xxx = []` or `this.xxx = {}` in `new` to avoid multiple instances sharing the same default reference.