After learning about Inheritence
, Encapsulation
, Polymorphism
, Abstraction
, and how to manifest in JavaScript
code when referencing from Java
; There are a few features that I feel are essential to finding the right way to represent. That is:
First , the Encapsulation
encapsulation feature borrows in part from the protected
label, which limits access to elements that are only available in the legacy line. The solution referenced from JavaScript.info is heavily reliant on self-generated logic conventions. That is, technically, elements named with _
in front of them are still public
and the coder will have to limit themselves to writing access to those elements.
Second , the ability to create a reference surface using an interface
to a compatible object
and hide all other elements unrelated to that interface
. This in OOP
is called a blackbox
, when the code uses an object
that doesn’t know the details of the object it is interacting with. The solution that I found earlier can only help to use interface
as an abstraction design tool, to create constraints for the writing phase of code that implements detailed logic.
Hmm… surely there must be another way of expressing logic that works like this. The general idea is that an example in the Java
environment, where the form of Multi-Inheritance
is not supported at the syntactic level of the language, was reimagined by creating a code architecture. called Object Composition
.
That is, instead of copying the elements present in the Trait
into the class
to use, people will attach each Trait
to a property in that class
. And when making access to an element in that Trait
, the syntax will be object.trait.method()
. A bit cumbersome, but the important thing is that the necessary feature has appeared.
So let’s try to do a few examples to see how Object Composition
can improve what OOP
tools in JavaScript
do not yet technically support.
Protected State
Since JavaScript
has no encapsulation logic at the directory level, so when borrowing the operation logic of the protected
label from Java
, what we want is: to be able to define non-open property
like public
, but also is not closed in the scope of that class
like #private
, but can be available in the scope of derived class
.
So, first, so that the property
are not open like public
, we will define them all as #private
.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | <span class="token keyword">class</span> <span class="token class-name">Person</span> <span class="token punctuation">{</span> #name <span class="token operator">=</span> <span class="token string">"Somebody"</span> #age <span class="token operator">=</span> <span class="token number">1001</span> <span class="token keyword">do</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> console <span class="token punctuation">.</span> <span class="token function">log</span> <span class="token punctuation">(</span> <span class="token string">"Just a method"</span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token comment">//. Person</span> <span class="token comment">// - main - - - - - - - - -</span> <span class="token keyword">var</span> wukong <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Person</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> console <span class="token punctuation">.</span> <span class="token function">log</span> <span class="token punctuation">(</span> wukong <span class="token punctuation">.</span> #name <span class="token punctuation">)</span> <span class="token comment">// - error: #name is private</span> |
However, now we also want class
that inherit Person
to also have direct access to these properties. That is, it is necessary to support the extends
operation that can bring these properties from the class Person
to the derived class
.
If so, now we need these properties to be made public
when we perform the inheritance operation. And this is only possible if we separate the properties into another class
.
Here, I temporarily use the word Entity
(entity) to name representative class
, with additional method
describing the ability to act, interact, and simulate human entities; The word Record
is used to name the data class
, describing a record in the database
.
Considering the interface using class Entity
, the #state
are private
, so it is possible to limit the accessibility from the code defined outside the inheritance line. As for the class Record
, the name
, age
, etc. data fields are all public
, so they can be inherited by other class Record
.
So in case PersonRecord
contains many state properties, we can be supported by extends
operation and do not have to redefine when we need to create a class
that inherits PersonEntity
.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | <span class="token keyword">const</span> Person <span class="token operator">=</span> <span class="token punctuation">{</span> <span class="token comment">/* namespace */</span> <span class="token punctuation">}</span> <span class="token keyword">const</span> VNese <span class="token operator">=</span> <span class="token punctuation">{</span> <span class="token comment">/* namespace */</span> <span class="token punctuation">}</span> Person <span class="token punctuation">.</span> Record <span class="token operator">=</span> <span class="token keyword">class</span> <span class="token punctuation">{</span> name <span class="token operator">=</span> <span class="token string">"Someone"</span> age <span class="token operator">=</span> <span class="token number">1001</span> <span class="token punctuation">}</span> <span class="token comment">//...Record</span> Person <span class="token punctuation">.</span> Entity <span class="token operator">=</span> <span class="token keyword">class</span> <span class="token punctuation">{</span> #state <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Person <span class="token punctuation">.</span> Record</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token keyword">do</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> console <span class="token punctuation">.</span> <span class="token function">log</span> <span class="token punctuation">(</span> <span class="token string">"Just a method."</span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token comment">//...Entity</span> VNese <span class="token punctuation">.</span> Record <span class="token operator">=</span> <span class="token keyword">class</span> <span class="token class-name">extends</span> Person <span class="token punctuation">.</span> Record <span class="token punctuation">{</span> jobs <span class="token operator">=</span> <span class="token punctuation">[</span> <span class="token string">"crafter"</span> <span class="token punctuation">,</span> <span class="token string">"teacher"</span> <span class="token punctuation">]</span> <span class="token punctuation">}</span> <span class="token comment">//..Record</span> VNese <span class="token punctuation">.</span> Entity <span class="token operator">=</span> <span class="token keyword">class</span> <span class="token class-name">extends</span> Person <span class="token punctuation">.</span> Entity <span class="token punctuation">{</span> #state <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">VNese <span class="token punctuation">.</span> Record</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token function">intro</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> console <span class="token punctuation">.</span> <span class="token function">log</span> <span class="token punctuation">(</span> <span class="token keyword">this</span> <span class="token punctuation">.</span> #state <span class="token punctuation">.</span> name <span class="token punctuation">)</span> console <span class="token punctuation">.</span> <span class="token function">log</span> <span class="token punctuation">(</span> <span class="token keyword">this</span> <span class="token punctuation">.</span> #state <span class="token punctuation">.</span> age <span class="token punctuation">)</span> console <span class="token punctuation">.</span> <span class="token function">log</span> <span class="token punctuation">(</span> <span class="token keyword">this</span> <span class="token punctuation">.</span> #state <span class="token punctuation">.</span> jobs <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token comment">//..Entity</span> <span class="token comment">// - main - - - - - - - - -</span> wukong <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">VNese <span class="token punctuation">.</span> Entity</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> wukong <span class="token punctuation">.</span> <span class="token function">intro</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token comment">// Ok</span> console <span class="token punctuation">.</span> <span class="token function">log</span> <span class="token punctuation">(</span> wukong <span class="token punctuation">.</span> #name <span class="token punctuation">)</span> <span class="token comment">// Error</span> |
1 2 3 4 5 6 7 8 9 10 11 12 | node main.js Someone 1001 [ 'crafter', 'teacher' ] /home/semiart/Documents/draft-code/main.js:38 wukong.#name () ^ SyntaxError: Private field '#name' must be declared in an enclosing class |
So we have #name
available to the code defined inside the derived class
and hidden from the code defined outside. The way to handle protected state
for abstract class
is completely similar, so we don’t need to add example code anymore.
Regarding the encapsulation of method method
, it is not really necessary, because in fact, method
that need to be hidden in private
or protected
form are all a kind of sub-program
that supports method
to open in public
form. And so we can all turn into sub-program
defined outside the class
space, then from the main method
will be able to pass in the necessary parameters the sub-program
support.
Blackbox Referencing
First of all, let’s review this feature in Java
that we already know through the example of the previous article. Let’s say we have a class Person
that implements
the Crafter
and Teacher
interfaces. An operation referencing the interface Crafter
will not be able to use methods not declared in that interface
.
1 2 3 4 5 | <span class="token keyword">interface</span> <span class="token class-name">Crafter</span> <span class="token punctuation">{</span> <span class="token keyword">void</span> work <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token keyword">void</span> rest <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> |
1 2 3 4 5 | <span class="token keyword">interface</span> <span class="token class-name">Teacher</span> <span class="token punctuation">{</span> <span class="token keyword">void</span> intro <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token keyword">void</span> teach <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> |
1 2 3 4 5 6 7 8 | <span class="token class-name">Person</span> someone <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Person</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token class-name">Teacher</span> asteacher <span class="token operator">=</span> someone <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> asteacher <span class="token punctuation">.</span> teach <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token comment">// Ok</span> <span class="token class-name">Crafter</span> ascrafter <span class="token operator">=</span> someone <span class="token punctuation">;</span> ascrafter <span class="token punctuation">.</span> teach <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token comment">// Error</span> |
This feature is implemented in Java
because the identifier names are all well-typed and the compiler will be able to perform lookup logic to the definition of the interface
in use. However, for a dynamic-typing
language like JavaScript
, we need to find a solution ourselves. Will still be Object Composition
. And here is the reference through an interface
in JavaScript
:
1 2 3 4 5 6 7 8 9 | <span class="token keyword">var</span> someone <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Person <span class="token punctuation">.</span> Entity</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token keyword">var</span> <span class="token punctuation">{</span> asteacher <span class="token punctuation">}</span> <span class="token operator">=</span> someone asteach <span class="token punctuation">.</span> <span class="token function">intro</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> asteach <span class="token punctuation">.</span> <span class="token function">teach</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token comment">// Ok</span> <span class="token keyword">var</span> <span class="token punctuation">{</span> ascrafter <span class="token punctuation">}</span> <span class="token operator">=</span> someone ascrafter <span class="token punctuation">.</span> <span class="token function">teach</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token comment">// Error</span> |
That means each interface
will need to be implemented with a corresponding trait
and attached to a property of the class Entity
that uses that trait
.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 | <span class="token keyword">const</span> Person <span class="token operator">=</span> <span class="token punctuation">{</span> <span class="token comment">/* Entity */</span> <span class="token punctuation">}</span> <span class="token keyword">const</span> Teacher <span class="token operator">=</span> <span class="token punctuation">{</span> <span class="token comment">/* Trait */</span> <span class="token punctuation">}</span> Person <span class="token punctuation">.</span> Record <span class="token operator">=</span> <span class="token keyword">class</span> <span class="token punctuation">{</span> name <span class="token operator">=</span> <span class="token string">"Someone"</span> age <span class="token operator">=</span> <span class="token number">1001</span> <span class="token function">constructor</span> <span class="token punctuation">(</span> <span class="token parameter">name <span class="token punctuation">,</span> age <span class="token punctuation">,</span> knowledge</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">this</span> <span class="token punctuation">.</span> name <span class="token operator">=</span> name <span class="token keyword">this</span> <span class="token punctuation">.</span> age <span class="token operator">=</span> age <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token comment">//...Record</span> Person <span class="token punctuation">.</span> Entity <span class="token operator">=</span> <span class="token keyword">class</span> <span class="token punctuation">{</span> #state <span class="token operator">=</span> <span class="token keyword">null</span> asteacher <span class="token operator">=</span> <span class="token keyword">null</span> ascrafter <span class="token operator">=</span> <span class="token keyword">null</span> <span class="token function">constructor</span> <span class="token punctuation">(</span> <span class="token parameter">name <span class="token punctuation">,</span> age <span class="token punctuation">,</span> knowledge</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">this</span> <span class="token punctuation">.</span> #state <span class="token operator">=</span> <span class="token punctuation">{</span> <span class="token comment">/* empty */</span> <span class="token punctuation">}</span> <span class="token comment">// - uses Traits</span> <span class="token keyword">this</span> <span class="token punctuation">.</span> asteacher <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Teacher <span class="token punctuation">.</span> Trait</span> <span class="token punctuation">(</span> <span class="token keyword">this</span> <span class="token punctuation">.</span> #state <span class="token punctuation">,</span> knowledge <span class="token punctuation">)</span> <span class="token keyword">this</span> <span class="token punctuation">.</span> ascrafter <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Object</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token comment">// Crafter.Trait</span> <span class="token comment">// - override Properties in Traits</span> Object <span class="token punctuation">.</span> <span class="token function">assign</span> <span class="token punctuation">(</span> <span class="token keyword">this</span> <span class="token punctuation">.</span> #state <span class="token punctuation">,</span> <span class="token keyword">new</span> <span class="token class-name">Person <span class="token punctuation">.</span> Record</span> <span class="token punctuation">(</span> name <span class="token punctuation">,</span> age <span class="token punctuation">)</span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token comment">//...Entity</span> Teacher <span class="token punctuation">.</span> Record <span class="token operator">=</span> <span class="token keyword">class</span> <span class="token punctuation">{</span> knowledge <span class="token operator">=</span> <span class="token number">1001</span> <span class="token function">constructor</span> <span class="token punctuation">(</span> <span class="token parameter">knowledge</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">this</span> <span class="token punctuation">.</span> knowledge <span class="token operator">=</span> knowledge <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token comment">//....Record</span> Teacher <span class="token punctuation">.</span> Trait <span class="token operator">=</span> <span class="token keyword">class</span> <span class="token punctuation">{</span> #state <span class="token operator">=</span> <span class="token keyword">null</span> <span class="token function">constructor</span> <span class="token punctuation">(</span> <span class="token parameter">superstate <span class="token punctuation">,</span> knowledge</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">this</span> <span class="token punctuation">.</span> #state <span class="token operator">=</span> superstate <span class="token keyword">var</span> record <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Teacher <span class="token punctuation">.</span> Record</span> <span class="token punctuation">(</span> knowledge <span class="token punctuation">)</span> Object <span class="token punctuation">.</span> <span class="token function">assign</span> <span class="token punctuation">(</span> <span class="token keyword">this</span> <span class="token punctuation">.</span> #state <span class="token punctuation">,</span> record <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token function">intro</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> console <span class="token punctuation">.</span> <span class="token function">log</span> <span class="token punctuation">(</span> <span class="token string">"As a teacher.."</span> <span class="token punctuation">)</span> console <span class="token punctuation">.</span> <span class="token function">log</span> <span class="token punctuation">(</span> <span class="token string">"Name: "</span> <span class="token operator">+</span> <span class="token keyword">this</span> <span class="token punctuation">.</span> #state <span class="token punctuation">.</span> name <span class="token punctuation">)</span> console <span class="token punctuation">.</span> <span class="token function">log</span> <span class="token punctuation">(</span> <span class="token string">"Age: "</span> <span class="token operator">+</span> <span class="token keyword">this</span> <span class="token punctuation">.</span> #state <span class="token punctuation">.</span> age <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token function">teach</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> console <span class="token punctuation">.</span> <span class="token function">log</span> <span class="token punctuation">(</span> <span class="token string">"Knowledge: "</span> <span class="token operator">+</span> <span class="token keyword">this</span> <span class="token punctuation">.</span> #state <span class="token punctuation">.</span> knowledge <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token comment">//....Trait</span> <span class="token comment">// - main - - - - - - - - -</span> wukong <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Person <span class="token punctuation">.</span> Entity</span> <span class="token punctuation">(</span> <span class="token string">"Wukong"</span> <span class="token punctuation">,</span> <span class="token number">500</span> <span class="token punctuation">,</span> <span class="token number">72</span> <span class="token punctuation">)</span> <span class="token keyword">var</span> <span class="token punctuation">{</span> asteacher <span class="token punctuation">}</span> <span class="token operator">=</span> wukong asteacher <span class="token punctuation">.</span> <span class="token function">intro</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token comment">// Ok</span> asteacher <span class="token punctuation">.</span> <span class="token function">teach</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token comment">// Ok</span> <span class="token keyword">var</span> <span class="token punctuation">{</span> ascrafter <span class="token punctuation">}</span> <span class="token operator">=</span> wukong ascrafter <span class="token punctuation">.</span> <span class="token function">teach</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token comment">// Error</span> |
Here is a little note in the example code of the trait
, usually the trait
will be defined with all the property
needed to be used for the method method
present in that trait
. However, to clarify the logic of referencing the superstate
, I did not define name
and age
in the trait Teacher.Record
.
Where ascrafter = new Crafter.Trait()
uses an empty new Object()
instead for the symbol; Since we are just trying to refer to the teach()
method which is not in the design of Crafter.Trait
.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | node main.js As a teacher.. Name: Wukong Age: 500 Age: 72 Knowledge: 1001 /home/semiart/Documents/draft-code/main.js:69 ascrafter.teach () ^ TypeError: ascrafter.teach is not a function |
Oh.. and with this implementation, if we want a property
in wukong.#state
that can be opened for external code to use, we can create an additional trait
named like asaccess
that holds the parameter refer to #superstate
.
The asaccess
will then be able to externally provide the public
and return #state.property
open methods it wants to open. As such, we can still decide which property
will be accessible at the public
or protected
level if desired.
summary
So with the class Entity
design consisting of a single object #state
and object trait
that hold a reference to superstate = entity.#state
. We were able to really borrow the operation logic of protected property
and limit reference via the interface
of a statically typed language like Java
.
In addition to the related concepts introduced, OOP
has another popular category called Design Patterns
. If you have time to learn more about this topic, here I have a series of translations from Tutorialspoint.com: [Design Patterns] Một Số Dạng Thức Triển Khai Trong OOP
.
And a Series that I follow, translated in detail from Refactoring.guru: Design Patterns - Ren
This is also the last article in this series of articles introducing OOP
in this Sub-Series. And now we will move on to another programming paradigm called Event-Driven Programming
.
(unpublished) [JavaScript] Lesson 31 – Event-Driven Programming