<commit_before># Obj

Obj is an [Ash](https://github.com/ash-shell/ash) module that adds object support to Bash.

# Getting started

Obj is part of the Ash core, so you can just start using it in your Ash modules.

For an example of an ash module that uses objects, [look here](https://github.com/BrandonRomano/ash-obj-examples).

# Features + Usage

## Imports

Before we can start using any objects, we must first import them.

If the objects you want to use are in your current module, they are already imported for you.

If the objects you want to use are outside of your current module, you must import them. You can import an external module with `Obj__import`:

```bash
Obj__import "$package_to_import" "$package_alias"
```

`$package_to_import` is the modules package (as specified in its `ash_config.yaml` file), while `$package_alias` is the alias in which we will refer to the newly imported package.

If I have `https://github.com/BrandonRomano/ash-obj-examples` installed and would like to import its classes in a different module, I would this following line to my module:

```bash
Obj__import "github.com/BrandonRomano/ash-obj-examples" "objex"
```

> External modules must first be installed before importing them.  See [apm](https://github.com/ash-shell/apm).

## Creating Classes

Before getting into any details, as you would expect classes are the definition of what an object is.

Classes must be placed in the directory defined to hold classes (for Ash users, this is in a directory named `classes` in the root of your module).  Classes also must be named as their classname with `.sh` as their extension.  By convention, you should use [PascalCase](http://c2.com/cgi/wiki?PascalCase) for class naming as many modern programming languages use.

> For example, if I were to create a class that would define what a Person object is, I would name the file `Person.sh`.

I'll explain the different components of what a class is below, but here is what a class looks like.  This would be in a file named Person.sh in our classes diretory:

> For a fully commented version of this class, look [here](https://github.com/ash-shell/obj-examples/blob/master/classes/Person.sh)

```bash
#!/bin/bash
# This is a simple class that represents a Person.

Person__id=""
Person__name=""
Person__age=""

Person_birthdays_count=0

Person__construct(){
    Person__id="$1"
    Person__name="$2"
    Person__age="$3"
}

Person__make_older(){
    Person__age=$((Person__age+1))
    Person_update_birthday_count
}

Person_update_birthday_count(){
    Person_birthdays_count=$((Person_birthdays_count+1))
    echo "Happy Birthday $Person__name!"
    echo "This is birthday #$Person_birthdays_count we have celebrated with $Person__name."; echo
}
```

### Public Members

Public members are variables that are bound to an object, that may be both fetched and updated from outside the scope of the class.

A public member is denoted by the Class name followed by two underscores `__`.

> Following our example above, `Person__id` is a public member.

### Private Members

Private members are variables that are bound to an object, but may not be accessed from outside the scope of the class.  These are very powerful, as they allow you to manage state within an object without exposing additional information.

A private member is denoted by the Class name followed by a single underscore `_`.

> Following our example above, `Person_birthdays_count` is a private member.

### Public Methods

Public methods are functions bound within an object that have access to all of the public/private members.  Public methods also have access to all other public/private methods.  Public methods may be called from outside of the scope of the object.

A public method is a function denoted by the Class name followed by two underscores `__`.

> Following our example above, `Person__make_older` is a public method.

### Private Methods

Private methods are functions bound within an object that have access to all of the public/private members. Private methods also have access to all other public/private methods.  Private methods may *not* be called from outside of the scope of the object, and are to only be used internally.

A private method is a function denoted by the Class name followed by a single underscore `_`.

> Following our example above, `Person_update_birthday_count` is a private method.

### Constructors

Constructors are magically named funcitons that get called when an object is initialized.  Constructors can take an arbitrary amount of parameters, and have all of the same powers as a public method (as it technically is a public method).

A constructor is a function denoted by the class name followed by `__construct`.

> Following our example above, `Person__construct` is our constructor.

## Creating and Using Objects

Now that we've created this cool class, I'd imagine now we would want to use it.

### Objects by Reference

It's worth noting that all objects created will be by reference (or by means of pointer).

This makes this library work extremely well with bash, as these pointers are just strings that can be dealt with in any way that bash currently supports.  This allows you to throw objects into arrays, use them as parameters to functions, use them in subshells, etc, all without any additional extension to Bash.

### Instantiating Objects (Obj__alloc / Obj__init)

To create an object, there are two steps.  First we have to allocate a pointer for the object, then we have to initialize the object.

To allocate a pointer for an object, we must use `Obj__alloc`, which is passed a class name.  Object alloc will return the pointer you will use to refer to the object, so hold onto this!

To initialize an object, we must use `Obj__init`, which is passed the object pointer.  You may pass any additional parameters after this, and they will get passed along to the objects construct method.

For example, if I wanted to create a new person object that represents myself, I would do this:

```bash
brandon=$(Obj__alloc "Person")
Obj__init $brandon 1 "Brandon" 23
```

Now I have a reference to `$brandon`, which is a pointer to a initialized object representing myself.

##### A quick Obj__init Gotcha

It's worth nothing that if you use `Obj__init` within a subshell, the object will only be initialized within the scope of that subshell.  Your best bet is to not wrap this call in a subshell unless you really know what you're doing.  However, we are allowed to pass objects into subshells after they have been initialized.  This follows the same rules as variables in a subshell:

> Variables in a subshell are not visible outside the block of code in the subshell. They are not accessible to the parent process, to the shell that launched the subshell. These are, in effect, variables local to the child process. - [tldp.org](http://www.tldp.org/LDP/abs/html/subshells.html)

### Object Dump for Debugging (Obj__dump)

It's very useful to find out the state of a current object when trying to debug a script.

If I were to run `Obj__dump $brandon`, immediately after initializing the object in the last section, it would output:

```
====== Person_4D69741E8CB76419 ======
| age=23
| id=3
| name='<NAME>'
=====================================
```

As you can see, `Obj__dump` prints out all of the public variables in an object.

### Setters + Getters

As mentioned in previous sections, public members can be accessed / updated.

#### Updating Member Variables (Obj__set)

To update a public member belonging to an object, you can use `Obj__set`.

There are three parameters to `Obj__set`.

The first is the object pointer itself that was returned by `Obj__alloc`.

The second is the name of the public member variable.  This does not include the in-class `ClassName__` prefix.  If in your class you had a member `Person__name`, you would simply pass `name`.

The third is the new value you would like to set to that member variable.

```bash
Obj__set $brandon name "<NAME>"
```

An `Obj__dump` on our `$brandon` object would now yield:

```
====== Person_4D69741E8CB76419 ======
| age=23
| id=3
| name='<NAME>'
=====================================
```

#### Accessing Member Variables (Obj__get)

To get the value of a public member belonging to an object, you can use `Obj__get`.

There are two parameters to `Obj__get`.

The first is the object pointer itself that was returned by `Obj__alloc`.

The second is the variable name, following the same rules as discussed in the previous section.

If I were to now run:

```bash
myname=$(Obj__get $brandon name)
echo $myname
```

It would output:

```
<NAME>
```

### Calling Public Methods

Inside of a class, methods are called with the full name of the function (e.g. `Person__make_older`).

Outside of the class, this is different, and public methods must be called via `Obj__call`.

There are two required parameters to `Obj__call`.

The first is the object pointer itself that was returned by `Obj__alloc`.

The second is the method name. This does not include the in-class `ClassName__` prefix.  If in your class you had a public method `Person__make_older`, you would simply pass `make_older`.

Following our example, we could call:

```
Obj__call $brandon make_older
```<commit_msg>Update README for package imports update<commit_after># Obj

Obj is an [Ash](https://github.com/ash-shell/ash) module that adds object support to Bash.

# Getting started

Obj is part of the Ash core, so you can just start using it in your Ash modules.

For an example of an ash module that uses objects, [look here](https://github.com/BrandonRomano/ash-obj-examples).

# Features + Usage

## Imports

Before we can start using any objects, we must first import them.

If the objects you want to use are in your current module, they are already imported for you.

If the objects you want to use are outside of your current module, you must import them. You can import an external module with `Obj__import`:

```bash
Obj__import "$package_to_import" "$package_alias"
```

`$package_to_import` is the modules package (as specified in its `ash_config.yaml` file), while `$package_alias` is the alias in which we will refer to the newly imported package.

If I have `https://github.com/BrandonRomano/ash-obj-examples` installed and would like to import its classes in a different module, I would this following line to my module:

```bash
Obj__import "github.com/BrandonRomano/ash-obj-examples" "objex"
```

> External modules must first be installed before importing them.  See [apm](https://github.com/ash-shell/apm).

## Creating Classes

Before getting into any details, as you would expect classes are the definition of what an object is.

Classes must be placed in the directory named `classes` in the root of a module.  Classes also must be named as their classname with `.sh` as their extension.  By convention, you should use [PascalCase](http://c2.com/cgi/wiki?PascalCase) for class naming as many modern programming languages use.

> For example, if I were to create a class that would define what a Person object is, I would name the file `Person.sh`.

I'll explain the different components of what a class is below, but here is what a class looks like.  This would be in a file named Person.sh in our classes diretory:

> For a fully commented version of this class, look [here](https://github.com/BrandonRomano/ash-obj-examples/blob/master/classes/Person.sh)

```bash
#!/bin/bash
# This is a simple class that represents a Person.

Person__id=""
Person__name=""
Person__age=""

Person_birthdays_count=0

Person__construct(){
    Person__id="$1"
    Person__name="$2"
    Person__age="$3"
}

Person__make_older(){
    Person__age=$((Person__age+1))
    Person_update_birthday_count
}

Person_update_birthday_count(){
    Person_birthdays_count=$((Person_birthdays_count+1))
    echo "Happy Birthday $Person__name!"
    echo "This is birthday #$Person_birthdays_count we have celebrated with $Person__name."; echo
}
```

### Public Members

Public members are variables that are bound to an object, that may be both fetched and updated from outside the scope of the class.

A public member is denoted by the Class name followed by two underscores `__`.

> Following our example above, `Person__id` is a public member.

### Private Members

Private members are variables that are bound to an object, but may not be accessed from outside the scope of the class.  These are very powerful, as they allow you to manage state within an object without exposing additional information.

A private member is denoted by the Class name followed by a single underscore `_`.

> Following our example above, `Person_birthdays_count` is a private member.

### Public Methods

Public methods are functions bound within an object that have access to all of the public/private members.  Public methods also have access to all other public/private methods.  Public methods may be called from outside of the scope of the object.

A public method is a function denoted by the Class name followed by two underscores `__`.

> Following our example above, `Person__make_older` is a public method.

### Private Methods

Private methods are functions bound within an object that have access to all of the public/private members. Private methods also have access to all other public/private methods.  Private methods may *not* be called from outside of the scope of the object, and are to only be used internally.

A private method is a function denoted by the Class name followed by a single underscore `_`.

> Following our example above, `Person_update_birthday_count` is a private method.

### Constructors

Constructors are magically named funcitons that get called when an object is initialized.  Constructors can take an arbitrary amount of parameters, and have all of the same powers as a public method (as it technically is just a public method).

A constructor is a function denoted by the class name followed by `__construct`.

> Following our example above, `Person__construct` is our constructor.

## Creating and Using Objects

Now that we've created this cool class, I'd imagine now we would want to use it.

### Objects by Reference

It's worth noting that all objects created will be by reference (or by means of pointer).

This makes this library work extremely well with bash, as these pointers are just strings that can be dealt with in any way that bash currently supports.  This allows you to throw objects into arrays, use them as parameters to functions, use them in subshells, etc, all without any additional extension to Bash.

### Instantiating Objects (Obj__alloc / Obj__init)

To create an object, there are two steps.  First we have to allocate a pointer for the object, then we have to initialize the object.

To allocate a pointer for an object, we must use `Obj__alloc`, which is passed a class name.  Object alloc will return the pointer you will use to refer to the object, so hold onto this!

To initialize an object, we must use `Obj__init`, which is passed the object pointer.  You may pass any additional parameters after this, and they will get passed along to the objects construct method.

For example, if I wanted to create a new person object that represents myself, I would do this:

```bash
brandon=$(Obj__alloc "Person")
Obj__init $brandon 1 "Brandon" 23
```

Now I have a reference to `$brandon`, which is a pointer to a initialized object representing myself.

##### From an External Package

If I wanted to create an object from an external package that I've imported, we must specify the package alias in `Obj__alloc`, in `alias.ClassName` format:

```bash
# Importing
Obj__import "github.com/BrandonRomano/ash-obj-examples" "objex"

# Creating the Object
brandon=$(Obj__alloc "objex.Person")  # Note the `objex.` before the class name
Obj__init $brandon 1 "Brandon" 23
```

> When you're creating an object from the current context, you could actually say `this.ClassName` - Although, it isn't necessisary because if you don't specify a package, `Obj__alloc` by default assumes you mean `this`.

##### A quick Obj__init Gotcha

It's worth nothing that if you use `Obj__init` within a subshell, the object will only be initialized within the scope of that subshell.  Your best bet is to not wrap this call in a subshell unless you really know what you're doing.  However, we are allowed to pass objects into subshells after they have been initialized.  This follows the same rules as variables in a subshell:

> Variables in a subshell are not visible outside the block of code in the subshell. They are not accessible to the parent process, to the shell that launched the subshell. These are, in effect, variables local to the child process. - [tldp.org](http://www.tldp.org/LDP/abs/html/subshells.html)

### Object Dump for Debugging (Obj__dump)

It's very useful to find out the state of a current object when trying to debug a script.

If I were to run `Obj__dump $brandon`, immediately after initializing the object in the last section, it would output:

```
====== Person_4D69741E8CB76419 ======
| age=23
| id=3
| name='<NAME>'
```

As you can see, `Obj__dump` prints out all of the public variables in an object.

### Setters + Getters

As mentioned in previous sections, public members can be accessed / updated.

#### Updating Member Variables (Obj__set)

To update a public member belonging to an object, you can use `Obj__set`.

There are three parameters to `Obj__set`.

The first is the object pointer itself that was returned by `Obj__alloc`.

The second is the name of the public member variable.  This does not include the in-class `ClassName__` prefix.  If in your class you had a member `Person__name`, you would simply pass `name`.

The third is the new value you would like to set to that member variable.

```bash
Obj__set $brandon name "<NAME>"
```

An `Obj__dump` on our `$brandon` object would now yield:

```
====== Person_4D69741E8CB76419 ======
| age=23
| id=3
| name='<NAME>'
```

#### Accessing Member Variables (Obj__get)

To get the value of a public member belonging to an object, you can use `Obj__get`.

There are two parameters to `Obj__get`.

The first is the object pointer itself that was returned by `Obj__alloc`.

The second is the variable name, following the same rules as discussed in the previous section.

If I were to now run:

```bash
myname=$(Obj__get $brandon name)
echo $myname
```

It would output:

```
<NAME>
```

### Calling Public Methods

Inside of a class, all methods are called with the full name of the function (e.g. `Person__make_older`).

Outside of the class, this is different, and public methods must be called via `Obj__call`.

There are two required parameters to `Obj__call`.

The first is the object pointer itself that was returned by `Obj__alloc`.

The second is the method name. This does not include the in-class `ClassName__` prefix.  If in your class you had a public method `Person__make_older`, you would simply pass `make_older`.

Following our example, we could call:

```
Obj__call $brandon make_older
```
{'fraction_non_alphanumeric': 0.07310048698748495, 'fraction_numerical': 0.0043462323925223855, 'mean_word_length': 4.44568006843456, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 30, 'https://': 10, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2417508', 'n_tokens_mistral': 5222, 'n_tokens_neox': 5001, 'n_words': 2764}