Corrections to visibility portion of manual
parent
36ae6bcd81
commit
6037cef654
|
@ -320,21 +320,21 @@ Not accessible outside of the instance. Not inherited by subtypes.
|
||||||
|
|
||||||
By default, all members are public. This means that the members can be accessed
|
By default, all members are public. This means that the members can be accessed
|
||||||
and modified from within an instance and from outside. Subtypes (classes that
|
and modified from within an instance and from outside. Subtypes (classes that
|
||||||
inherit from it) will inherit the member. Public methods expose an API by which
|
inherit from it) will inherit public members. Public methods expose an API by
|
||||||
users may use your class. Public properties, however, should be less common, for
|
which users may use your class. Public properties, however, should be less
|
||||||
a very important reason.
|
common in practice for a very important reason, which is explored throughout the
|
||||||
|
rest of this section.
|
||||||
|
|
||||||
This introduces the concept of @dfn{encapsulation}, which is the act of hiding
|
@dfn{Encapsulation} is the act of hiding information within a class or instance.
|
||||||
information within a class or instance. Classes should be thought of black
|
Classes should be thought of black boxes. We want them to do their job, but we
|
||||||
boxes. We want them to do their job, but we do not care @emph{how} they do their
|
do not care @emph{how} they do their job. Encapsulation takes the complexity out
|
||||||
job. Encapsulation takes the complexity out of a situation and allows the
|
of a situation and allows the developer to focus on accomplishing the task using
|
||||||
developer to focus on accomplishing the task using familiar concepts. For
|
familiar concepts. For example, consider a class named @var{Dog} which has a
|
||||||
example, consider a class named @var{Dog} which has a method @code{walk()}. To
|
method @code{walk()}. To walk a dog, we simply call @code{Dog().walk()}. The
|
||||||
walk a dog, we simply call @code{Dog().walk()}. The @code{walk()} method could
|
@code{walk()} method could be doing anything. By preventing the details of the
|
||||||
be doing anything. By preventing the details of the method from being exposed,
|
method from being exposed, we present the developer with a very simple
|
||||||
we present the developer with a very simple interface. Rather than the developer
|
interface. Rather than the developer having to be concerned with moving each of
|
||||||
having to be concerned with moving each of the dog's legs, all they have to do
|
the dog's legs, all they have to do is understand that the dog is being walked.
|
||||||
is understand that the dog is being walked.
|
|
||||||
|
|
||||||
Let's consider our @var{Dog} class in more detail:
|
Let's consider our @var{Dog} class in more detail:
|
||||||
|
|
||||||
|
@ -366,7 +366,7 @@ Let's consider our @var{Dog} class in more detail:
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
'protected rollOver': function()
|
'public rollOver': function()
|
||||||
{
|
{
|
||||||
this._body.roll();
|
this._body.roll();
|
||||||
},
|
},
|
||||||
|
@ -402,17 +402,17 @@ everything as private and work from there.
|
||||||
@menu
|
@menu
|
||||||
* Private Members::
|
* Private Members::
|
||||||
* Protected Members::
|
* Protected Members::
|
||||||
|
* Visibility Escalation:: Increasing visibility of inherited members
|
||||||
@end menu
|
@end menu
|
||||||
|
|
||||||
@node Private Members
|
@node Private Members
|
||||||
@subsection Private Members
|
@subsection Private Members
|
||||||
Let's first explore private members. The majority of the members in the
|
Let's first explore private members. The majority of the members in the
|
||||||
@var{Dog} class are private. This is the lowest level of visibility (and
|
@var{Dog} class (@pxref{f:encapsulation,}) are private. This is the lowest level
|
||||||
consequently the @emph{highest} level of encapsulation). By convention, we
|
of visibility (and consequently the @emph{highest} level of encapsulation). By
|
||||||
prefix private members with an underscore. Private members are available
|
convention, we prefix private members with an underscore. Private members are
|
||||||
@emph{only to the class that defined it} and are not available outside the
|
available @emph{only to the class that defined it} and are not available outside
|
||||||
class. This means that we cannot call a private member from outside the class
|
the class.
|
||||||
define in @ref{f:encapsulation,}:
|
|
||||||
|
|
||||||
@float Figure, f:encapsulation-call-priv
|
@float Figure, f:encapsulation-call-priv
|
||||||
@verbatim
|
@verbatim
|
||||||
|
@ -424,12 +424,12 @@ define in @ref{f:encapsulation,}:
|
||||||
@caption{Cannot access private members outside the class}
|
@caption{Cannot access private members outside the class}
|
||||||
@end float
|
@end float
|
||||||
|
|
||||||
You will notice that the dog's legs are declared private as well. This is to
|
You will notice that the dog's legs are declared private as well
|
||||||
ensure we look at the dog as a whole. We don't care about what the dog is made
|
(@pxref{f:encapsulation,}). This is to ensure we look at the dog as a whole; we
|
||||||
up of. Legs, fur, tail, teeth, tongue, etc - they are all irrelevant to our
|
don't care about what the dog is made up of. Legs, fur, tail, teeth, tongue, etc
|
||||||
purpose. We just want to talk the dog. Encapsulating those details also ensures
|
- they are all irrelevant to our purpose. We just want to walk the dog.
|
||||||
that they will not be tampered with, which will keep the dog in a consistent,
|
Encapsulating those details also ensures that they will not be tampered with,
|
||||||
predictable state.
|
which will keep the dog in a consistent, predictable state.
|
||||||
|
|
||||||
Private members cannot be inherited. Let's say we want to make a class called
|
Private members cannot be inherited. Let's say we want to make a class called
|
||||||
@var{TwoLeggedDog} to represent a dog that was trained to walk only on two feet.
|
@var{TwoLeggedDog} to represent a dog that was trained to walk only on two feet.
|
||||||
|
@ -456,24 +456,24 @@ prevent the front legs from moving. What happens when we explore that approach:
|
||||||
@caption{Cannot override private members of supertype}
|
@caption{Cannot override private members of supertype}
|
||||||
@end float
|
@end float
|
||||||
|
|
||||||
If you were to attempt to walk the dog after attempting the above change, you
|
If you were to attempt to walk a @var{TwoLeggedDog}, you would find that
|
||||||
would find that @emph{the dog's front legs still move}! This is because, as
|
@emph{the dog's front legs still move}! This is because, as mentioned before,
|
||||||
mentioned before, private methods are not inherited. Rather than overriding the
|
private methods are not inherited. Rather than overriding the parent's
|
||||||
parent's @var{_moveFrontLeg} method, you are instead @emph{defining a new
|
@var{_moveFrontLeg} method, you are instead @emph{defining a new method}, with
|
||||||
method}, with the name @var{_moveFrontLeg}. The old method will still be called.
|
the name @var{_moveFrontLeg}. The old method will still be called. Instead, we
|
||||||
Instead, we would have to override the public @code{walk()} method to prevent
|
would have to override the public @var{walk} method to prevent our dog from
|
||||||
our dog from moving his front feet.
|
moving his front feet.
|
||||||
|
|
||||||
@node Protected Members
|
@node Protected Members
|
||||||
@subsection Protected Members
|
@subsection Protected Members
|
||||||
Protected members are often misunderstood. Many developers will declare all
|
Protected members are often misunderstood. Many developers will declare all
|
||||||
their members as either public or protected under the misconception that they
|
of their members as either public or protected under the misconception that they
|
||||||
may as well allow subclasses to override whatever functionality they want. This
|
may as well allow subclasses to override whatever functionality they want. This
|
||||||
makes the class more flexible.
|
makes the class more flexible.
|
||||||
|
|
||||||
While it is true that the class becomes more flexible to work with for subtypes,
|
While it is true that the class becomes more flexible to work with for subtypes,
|
||||||
this is a dangerous practice. In fact, doing so @emph{violates encapsulation}.
|
this is a dangerous practice. In fact, doing so @emph{violates encapsulation}.
|
||||||
Let's consider the levels of visibility in this manner:
|
Let's reconsider the levels of visibility in this manner:
|
||||||
|
|
||||||
@table @strong
|
@table @strong
|
||||||
@item public
|
@item public
|
||||||
|
@ -487,22 +487,24 @@ Provides an API for @emph{the class itself}.
|
||||||
@end table
|
@end table
|
||||||
|
|
||||||
Just as we want to hide data from the public API, we want to do the same for
|
Just as we want to hide data from the public API, we want to do the same for
|
||||||
subtypes. If we simply expose everything to any subclass that comes by, that
|
subtypes. If we simply expose all members to any subclass that comes by, that
|
||||||
acts as a peephole in our black box. We don't want people spying into our
|
acts as a peephole in our black box. We don't want people spying into our
|
||||||
internals. Subtypes shouldn't care about the dog's implementation either.
|
internals. Subtypes shouldn't care about the dog's implementation either.
|
||||||
|
|
||||||
@ref{Private Members,Private} members should be used whenever possible, unless
|
Private members (@pxref{Private Members,Private}) should be used whenever
|
||||||
you are looking to provide subtypes with the ability to access or override
|
possible, unless you are looking to provide subtypes with the ability to access
|
||||||
methods. In that case, we can move up to try protected members.
|
or override methods. In that case, we can move up to try protected members.
|
||||||
|
Remember not to make a member public unless you wish it to be accessible to the
|
||||||
|
entire world.
|
||||||
|
|
||||||
@ref{f:encapsulation,} defined a single method as protected - @code{stand()}.
|
@var{Dog} (@pxref{f:encapsulation,}) defined a single method as protected -
|
||||||
Because it is protected, it is able to be inherited by subtypes. Since it is
|
@code{stand()}. Because the method is protected, it can be inherited by
|
||||||
inherited, it may also be overridden. Let's define another subtype,
|
subtypes. Since it is inherited, it may also be overridden. Let's define another
|
||||||
@var{LazyDog}, which refuses to stand.
|
subtype, @var{LazyDog}, which refuses to stand.
|
||||||
|
|
||||||
@float Figure, f:encapsulation-inherit-prot
|
@float Figure, f:encapsulation-inherit-prot
|
||||||
@verbatim
|
@verbatim
|
||||||
var lazy_dog = Class( 'TwoLeggedDog' ).extend( Dog,
|
var lazy_dog = Class( 'LazyDog' ).extend( Dog,
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Overrides parent method
|
* Overrides parent method
|
||||||
|
|
Loading…
Reference in New Issue