Protected static members, abstract classes, object composition vs. subclassing

Discussion in 'Javascript' started by Kevin Prichard, Nov 26, 2005.

  1. Hi all,

    I've recently been following the object-oriented techiques discussed
    here and have been testing them for use in a web application. There is
    problem that I'd like to discuss with you experts.

    I would like to produce Javascript classes that can be "subclassed"
    with certain behaviors defined at subclass time. There are plenty of
    ways to do this through prototyping and other techniques, but these
    behaviors need to be static and protected. By protected this means
    that they can be overridden (or reassigned) in subclasses, and
    privileged subclass methods can access them, but callers external to
    the class cannot.

    I've been attempting to define a factory function that transfers its
    parameters to an anonymous object while defining the constructor in a
    -with- block. (This is what I'm loosely referring to as "subclassing"
    - it's really object composition.) This works, but not for
    externally-defined functions. They can't see the protected static
    members.

    // helper functions to be passed into factory function, for protected
    static use
    var ProtStaticMethod1 = function(that) { // caller passes in 'this'
    // call privileged bridge function to access protected static value
    alert("PSM1: "+that.GetPSField());
    };

    var ProtStaticMethod2 = function(that) {
    alert("PSM2: "+ProtStaticField);
    };

    // helper function, to be accessed as a privileged class method
    var candidateStaticMethod = function() {
    alert("PrivOutsiderSM: "+
    (typeof(ProtStaticField)=="undefined" ?
    "Outsider static method can't find ProtStaticField" : ProtStaticField)
    );
    };

    // factory function; params: 1) function, 2) any data
    var BaseFactory = function(psmMethod,psmField,privilegedMeth) {
    with ({
    ProtStaticField : psmField,
    ProtStaticMethod : psmMethod
    })
    {
    function Constructor() { // instance members just for fun
    var privInstMember = "privateMember";
    function privInstMethod() { alert(privInstMember); };
    };
    Constructor.prototype.ShowPSField = function() {
    alert("ShowPSField: "+ProtStaticField); }
    Constructor.prototype.InvokePSMethod = function() {
    ProtStaticMethod(this); }
    Constructor.prototype.SetPSField = function(val) {
    ProtStaticField=val; }
    Constructor.prototype.GetPSField = function() { return
    ProtStaticField; }
    Constructor.PrivOutsideMethod = privilegedMeth;
    Constructor.PrivInsideMethod = function() {
    alert("PrivInsiderSM: "+
    (typeof(ProtStaticField)=="undefined" ?
    "Can't find ProtStaticField" : ProtStaticField) );
    };
    };
    return Constructor;
    };
    SubClass1 = BaseFactory( ProtStaticMethod1, "ProtStaticField_Class1",
    candidateStaticMethod );
    // can a function defined outide the constructor's scope see privileged
    static fields?
    SubClass1.PrivOutsideMethod();

    SubClass2 = BaseFactory( ProtStaticMethod2, "ProtStaticField_Class2",
    candidateStaticMethod );
    // can a privileged static constructor method see protected static
    fields?
    SubClass1.PrivInsideMethod();

    obj1 = new SubClass1();
    obj2 = new SubClass2();
    obj1.ShowPSField(); // should display "ProtStaticField_Class1"
    obj2.ShowPSField(); // should display "ProtStaticField_Class2"
    obj1.InvokePSMethod(); // should display "ProtStaticField_Class1"
    obj2.InvokePSMethod(); // CRASH - ProtStaticMethod2 can't see
    ProtStaticField


    This has worked for producing subclasses whose protected static fields
    are composed of just about any values.

    BUT, my chief complaint is that functions defined outside the scope of
    the factory's -with- block aren't able to see the protected static
    members. Is that just a limitation of this technique, or is there
    something I need to change? The only thing that has worked at all is,
    as you can see, to add privileged bridge functions to the constructor's
    prototype. These act as a go-between for the externally defined
    functions stored, e.g. GetPSField as accessed by external function
    ProtStaticMethod1.

    Is there a better approach for producing "subclasses" whose protected
    static methods can be varied from outside, yet still access protected
    members?

    Thanks in advance for any feedback,

    Kevin Prichard
    Kevin Prichard, Nov 26, 2005
    #1
    1. Advertising

  2. Kevin Prichard

    VK Guest

    Kevin Prichard wrote:
    > Hi all,
    >
    > I've recently been following the object-oriented techiques discussed
    > here and have been testing them for use in a web application. There is
    > problem that I'd like to discuss with you experts.


    <snip>

    Wow - you really tried to get 100% out of JavaScript object model :)

    You may also want to look at my game records:

    <html>
    <head>
    <title>TMP</title>
    <meta http-equiv="Content-Type"
    content="text/html; charset=iso-8859-1">
    <script type="text/javascript">

    /**
    * myClassSuper is used as super class of myClass
    */
    function myClassSuper() {
    // Adds protected member <messenger>
    // from myClassUtils class:
    this.messenger = function(message) {
    this.utils.messenger(message);
    }
    }

    /**
    * Protected class myClassUtils
    * can be used only from within
    * myClass:
    */
    function myClassUtils(obj) {

    if (myClassUtils.caller !== myClass) {
    throw new Error("Get out of my protected stuff!");
    }

    this.messenger = function(message) {
    // JavaScript has a very weak feeling
    // of the context in objects. I would call
    // it "incontinence of <this>" :)
    // Any way:
    // alert(arguments.callee.caller);
    // gives you the public method of myClassSuper
    // - you may check against somehow.
    alert('myClassUtils.messenger says: '+message);
    }

    }


    /**
    * myClass constructor:
    */
    function myClass() {
    myClassSuper.call(this); // think super()
    this.utils = new myClassUtils(this);
    }

    function init() {

    try {
    var goodBoy = new myClass();
    goodBoy.messenger('Hi!');
    }
    catch(e) {
    alert(e.message);
    }

    try {
    var badBoy = new myClassUtils();
    badBoy.messenger('Hi!');
    }
    catch(e) {
    alert(e.message);
    }
    }
    </script>
    </head>

    <body onload="init();">

    </body>
    </html>

    Note [1]
    I'm using the <class> term as a convenience term. You are free to call
    it <prototype> or <constructor holder> or <foobar> or any other name.
    ;-)

    Note [2]
    JavaScript and Java are different languages but they have some things
    in common. In the particular interpreted nature of JavaScript and
    byte-coded (read: "interpreted") nature of Java makes them both open
    source languages.
    It means that protected/private/static/final stuff in them is not a
    bulletproof lock but merely an "inconvenience protection" (like locking
    context menu on the page). You always can study the code and/or spoof
    the constructor. In JavaScript it's easier than in Java - that's the
    only difference.
    So if you want to satisfy your boss, show him how the call to
    "protected" member leads to an exception. He should get happy. :)
    And you personally should remember that it's all an imaginary
    protection and you should never expose any sensitive data neither in
    public nor in protected/private members.

    I personally just ended up by naming all "protected" and "private"
    members with $_ + name. And I said in comments that if something starts
    with $_ then you should not touch it directly or the object may crash -
    and from this point out I simply washed my hands. This approach may be
    discutable but it saves hell a lot of time and space on
    {pseudo {clo}sure {protection}} which doesn't guarantee anything anyway.
    VK, Nov 27, 2005
    #2
    1. Advertising

  3. Kevin Prichard wrote:
    > I've recently been following the object-oriented techiques
    > discussed here and have been testing them for use in a web
    > application. There is problem that I'd like to discuss with
    > you experts.


    This is such a massive subject that I am a little included to let it go.

    Javascript is a dynamic language using prototype based inheritance for
    OO behaviour in which there are no access modifiers and no classes (or
    only one class, which is effectively the same thing). (Disregarding the
    unpublished and unknown ECMA 262 4th edition, JScript.net and JavaScript
    2, which are all irrelevant to client-side scripting and will remain so
    for some considerable time to come).

    The only Object type in javascript (the 'native ECMAScript object') is
    an unordered collection of name-value pairs, to which named properties
    can be added at runtime. So when an object can be considered to be or a
    distinct 'class' that distinction represents that fact that it is an
    instance of the one Object type that has been modified in a particular
    way that is common to all instances of the same 'class' but distinct
    from any processes that other 'classes' undergo.

    So, given a function that is to act as a constructor:-

    function MyObject(){
    ...
    }

    - and using the constructor with the new operator:-

    var inst = new MyObject();

    - the object instantiation process involves taking a new instance of the
    native ECMAScript object and changing its internal [[Prototype]]
    property from its default Null value to a reference to the object
    referred to by - MyObject.prototype - (but only if it does refer to an
    object), and then passing this native ECMAScript object to the execution
    of the function body as the - this - object, and finally returning the
    now modified native ECMAScript object (assuming that the execution of
    the function body does not explicitly return another object). The
    combination of a constructor function and its prototype define a process
    that is applied to a native ECMAScript object that modifies it in a way
    that allows the result to be considered as being of a distinct 'class'.

    However, describing objects created in this was of being of a 'class' is
    only a conceptual convenience. There always was only one Object type;
    the mutable native ECMAScript object, and because javascript is dynamic
    any object created as an instance of a 'class' is still open to run-time
    modification and may be stripped of the characteristics that define its
    ''class' or transformed into what for all practical purposes may be an
    instance of another 'class'.

    Of course in an OO design it would be unusual for an object that was
    conceptually of one 'class' to undergo runtime modification that
    prevented it form qualifying as that 'class' (at least once the desired
    'class' had been established, as the creation process may involve an
    initial instantiation of one 'class' followed by a sequence of specific
    additional modifications to create what will then be considered as being
    another (possibly 'sub') 'class').

    So, for convenience, the label 'class' can be attached to a category of
    object that have undergone a 'like' sequence of modifications in their
    creation, and are then not going to be subject to the types of run-time
    modification that would break their 'likeness'.

    This makes a 'class definition' the totality of code that applies these
    modification to what starts out as a native ECMAScript object, provided
    that code also does not undergo runtime modification that would change
    the 'likeness' of the resulting objects.

    Notice that this definition goes well beyond the combination of a
    constructor function and the assignment of properties to its prototype.
    Those are a long way short of being the only methods of crating object
    instances that have the 'likeness' that allows then the be considered as
    being of the same 'class'. (One of the reasons that javascript IDEs are
    not nearly as helpful as they can be in class-based language; it is
    difficult for software to see when the concept of 'class' is being
    implemented in javascript, so they usually give up and only recognise
    constructor/prototype combinations).

    Javascript also has no access modifiers. It is, for example, difficult
    to talk of a member being 'static' in a language that has no classes,
    and the properties of any object that it itself accessible are
    inevitably public.

    However, if the concept of 'class' is appropriate for use in describing
    javascript code it also becomes viable to talk of aspects of this code
    in terms of access modifiers.

    'Public instance member' may be appropriately applied to any property of
    an instance of a 'class', as they will be visible and accessible to all
    other code in the system.

    'Public static member' is usually applied to properties of a 'classes'
    constructor function, but may also apply to properties of an object that
    provides a method that acts as a factory for instances of a 'class'. The
    important aspect of 'static' is that it relates to a member that is 'of
    the class' rather than of instances of that class.

    Javascript needs no concept of 'public' because being public is what
    object properties are by default. But having no concept of 'private'
    might seem to preclude the possibility. However, it is in the nature of
    javascript that it can emulate anything; trading the effort of writing
    the emulation, and the overheads of executing it, for having a facility
    that is not naturally a part of the language.

    Rendering something 'private' is a matter of making it
    inaccessible/invisible outside of a particular context. And because
    javascript has closures, and closures allow code access to an
    environment that is inaccessible/invisible outside of the closure,
    javascript can emulate the concept of 'private'.

    'Private instance members' may be created by having the constructor (or
    factory) of an object form a closure, and the parameters, inner function
    declarations and local variables are preserved in the closure in a way
    that is inaccessible to code outside of the context of the constructor
    (or factory). It is not possible to form a closure without making a
    function object that was created within the context of a constructor (or
    factory) accessible outside of that context. It is also not useful to
    have 'private instance' members unless they can be interacted with by
    instances of the 'class'.

    The creation of the closure and the ability to access the 'private'
    members is usually facilitated through the process of evaluating
    function expressions within the context of the constructor (or factory)
    and assigning the result as a method of the object instance. These
    special methods of an object instance have been christened "Privileged"
    methods, as they have the privilege of being able to interact with the
    parameters, inner function declarations and local variables that
    represent the 'private instance' members.

    It is worth noting that this ability to access the 'private instance'
    members of an object instance is a quality that belongs to the function
    object that has been assigned as a method of the object instance, it is
    not related to the fact that that function object is an method of the
    object instance. This means that such a method may be hijacked and
    assigned as a method of a different object, or executed as a function,
    and will still have access to the 'private instance' members of the
    object instance.

    'Private static members' may be created by forming a closure with the
    constructor and/or the methods of the constructor's prototype. This
    involves creating the constructor and/or the methods of the prototype
    within another function, and it is the parameters, inner function
    declarations and local variables of that function that can be accessed
    by any code within that function but not outside of it, and so become
    the private static members. Accessible to all instances of that class
    but invisible to other code.

    Again it is the functions (including constructors) defined within the
    outermost function that have access to these 'private static' members,
    independently of their association with any objects.

    > I would like to produce Javascript classes that can be "subclassed"
    > with certain behaviors defined at subclass time. There are plenty of
    > ways to do this through prototyping and other techniques, but these
    > behaviors need to be static and protected. By protected this means
    > that they can be overridden (or reassigned) in subclasses, and
    > privileged subclass methods can access them, but callers external to
    > the class cannot.


    O.k. That is a definition of protected that is dissimilar to any I have
    considered. Are you trying to subclass dynamically, based upon runtime
    conditions? Otherwise I am not sure I see any issue here.

    > I've been attempting to define a factory function that transfers its
    > parameters to an anonymous object while defining the constructor in a
    > -with- block. (This is what I'm loosely referring to as "subclassing"
    > - it's really object composition.) This works, but not for
    > externally-defined functions. They can't see the protected static
    > members.


    If an externally defined function has access to the protected member in
    what sense would it b protected?

    > // helper functions to be passed into factory function, for protected
    > static use
    > var ProtStaticMethod1 = function(that) { // caller passes in 'this'
    > // call privileged bridge function to access protected static value
    > alert("PSM1: "+that.GetPSField());
    > };
    >
    > var ProtStaticMethod2 = function(that) {
    > alert("PSM2: "+ProtStaticField);
    > };


    There is no object on the scope chain of this function with the name
    'ProtStaticField' so the Identifier cannot be resolved. The scope chain
    of all function objects is defined and fixed at the point of creation of
    the function object, depending on the context in which that function
    object is created. You cannot add or remove objects from the scope chain
    once it has been created (though it is possible to add remove and modify
    the properties of objects on the scope chain so long as you have a
    reference to it.)

    > // helper function, to be accessed as a privileged class method
    > var candidateStaticMethod = function() {
    > alert("PrivOutsiderSM: "+
    > (typeof(ProtStaticField)=="undefined" ?
    > "Outsider static method can't find ProtStaticField" : ProtStaticField)
    > );
    > };


    Similarly 'ProtStaticField' is not a named property of any object on
    this function's scope chain.

    > // factory function; params: 1) function, 2) any data
    > var BaseFactory = function(psmMethod,psmField,privilegedMeth) {


    There is no reason for this to be a function expression.

    > with ({
    > ProtStaticField : psmField,
    > ProtStaticMethod : psmMethod
    > })


    If the - psmField - formal parameter was re-named to 'ProtStaticField'
    and the - psmMethod - parameter re-named to - ProtStaticMethod - the
    Activation/Valriable object for this execution context could take the
    palace of the object within the - with - statement, and the - with -
    statement could be avoided.

    > {
    > function Constructor() { // instance members just for fun
    > var privInstMember = "privateMember";
    > function privInstMethod() { alert(privInstMember); };
    > };


    Strictly this is a syntax error as a FunctionDeclaration may not appear
    in a Block statement. Browser environments mostly put up with this
    error, but behave differently. IE and Opera will create the constructor
    function outside of the - with - statement, while JavaScript(tm)
    environments will create the function object inside the - with -
    statement. Only a FunctionExpression should be allowed inside a Block
    statements so that would be the sensible way of creating the constructor
    inside a - with - statement. However, as the - with - statement is
    serving no useful purpose here FunctionDeclaration for the constructor
    could be retained by omitting the - with - statement, as then it would
    be outside of the Block statement.

    The result would resemble:-

    function BaseFactory(ProtStaticMethod,ProtStaticField,privilegedMeth){
    function Constructor() {
    var privInstMember = "privateMember";
    function privInstMethod() {
    alert(privInstMember);
    };
    };
    Constructor.prototype.ShowPSField = function() {
    alert("ShowPSField: " + ProtStaticField);
    };
    Constructor.prototype.InvokePSMethod = function() {
    ProtStaticMethod(this);
    };
    Constructor.prototype.SetPSField = function(val) {
    ProtStaticField = val;
    };
    Constructor.prototype.GetPSField = function() {
    returnProtStaticField;
    };
    Constructor.PrivOutsideMethod = privilegedMeth;
    Constructor.PrivInsideMethod = function() {
    alert("PrivInsiderSM: "+
    (typeof(ProtStaticField)=="undefined" ?
    "Can't find ProtStaticField" : ProtStaticField) );
    };
    return Constructor;
    }

    > Constructor.prototype.ShowPSField = function() {
    > alert("ShowPSField: "+ProtStaticField); }
    > Constructor.prototype.InvokePSMethod = function() {
    > ProtStaticMethod(this); }
    > Constructor.prototype.SetPSField = function(val) {
    > ProtStaticField=val; }
    > Constructor.prototype.GetPSField = function() { return
    > ProtStaticField; }
    > Constructor.PrivOutsideMethod = privilegedMeth;
    > Constructor.PrivInsideMethod = function() {
    > alert("PrivInsiderSM: "+
    > (typeof(ProtStaticField)=="undefined" ?
    > "Can't find ProtStaticField" : ProtStaticField) );
    > };
    > };
    > return Constructor;
    > };
    > SubClass1 = BaseFactory( ProtStaticMethod1, "ProtStaticField_Class1",
    > candidateStaticMethod );
    > // can a function defined outide the constructor's scope see
    > privileged static fields?
    > SubClass1.PrivOutsideMethod();
    >
    > SubClass2 = BaseFactory( ProtStaticMethod2, "ProtStaticField_Class2",
    > candidateStaticMethod );
    > // can a privileged static constructor method see protected static
    > fields?
    > SubClass1.PrivInsideMethod();
    >
    > obj1 = new SubClass1();
    > obj2 = new SubClass2();
    > obj1.ShowPSField(); // should display "ProtStaticField_Class1"
    > obj2.ShowPSField(); // should display "ProtStaticField_Class2"
    > obj1.InvokePSMethod(); // should display "ProtStaticField_Class1"
    > obj2.InvokePSMethod(); // CRASH - ProtStaticMethod2 can't see

    ^^^^^
    Not a crash, a runtime error, they are very different things.

    > ProtStaticField
    >
    >
    > This has worked for producing subclasses whose protected static
    > fields are composed of just about any values.
    >
    > BUT, my chief complaint is that functions defined outside the scope of
    > the factory's -with- block aren't able to see the protected static
    > members.


    The implication of javascript's lexical scoping is that they would not.

    > Is that just a limitation of this technique, or is there
    > something I need to change?


    It is a limitation of what this code is doing, but not necessarily a
    limitation of javascript. The problem with the above code is that it
    demonstrated how you are doing what you are doing, and so shows its
    limitations, it does not explain why you are doing it so it is not
    possible to judge whether the limitation shown applies to the real
    problem. It is unlikely that it really does.

    > The only thing that has worked at all is,
    > as you can see, to add privileged bridge functions to the
    > constructor's prototype. These act as a go-between for the
    > externally defined functions stored, e.g. GetPSField as accessed by
    > external function ProtStaticMethod1.


    One of the tings that I would question in the design is the use of these
    externally defined functions, or at lest how 'external' they really need
    to be.

    > Is there a better approach for producing "subclasses" whose
    > protected static methods can be varied from outside, yet still
    > access protected members?


    Be clear about the what and why of 'varied from outside', and the
    criteria for 'outside' and it may be possible to answer. When you are
    working with the more advanced aspects of javascript OO what you are
    really trying to do has an enormous impact upon what would qualify as
    the best way of doing it.

    Richard.
    Richard Cornford, Nov 27, 2005
    #3
  4. VK wrote:
    > Kevin Prichard wrote:

    <snip>
    > You may also want to look at my game records:


    I cannot speak for anyone else but I did not want to see it, and would
    rather never see it again.

    <snip>
    > /**
    > * Protected class myClassUtils
    > * can be used only from within
    > * myClass:


    Bullshit!

    > */
    > function myClassUtils(obj) {
    >
    > if (myClassUtils.caller !== myClass) {
    > throw new Error("Get out of my protected stuff!");
    > }


    The - caller - property of functions is a non-standard extension and so
    its use needlessly renders this code non-functional on all but a limited
    number of browsers (excluding, for example, Opera).

    This code throws an exception at the point of calling this function.
    While most concepts of 'protection' extend to the employment of objects
    at runtime.
    <snip>
    > Note [1]
    > I'm using the <class> term as a convenience term. You are free to call
    > it <prototype> or <constructor holder> or <foobar> or any other name.
    > ;-)
    >
    > Note [2]

    <snip - irrelevance>
    > It means that protected/private/static/final stuff in them is
    > not a bulletproof lock but merely an "inconvenience protection"
    > (like locking context menu on the page). You always can study
    > the code and/or spoof the constructor. In JavaScript it's
    > easier than in Java - that's the only difference.


    It is difficult to see how having had your limited understanding of
    programming pointed out to you so often you still fail to see your
    understanding as misconceived. Access modifiers have nothing to do with
    rendering the contents of object members secret, they are about imposing
    control over how object interact with each other, and particularly which
    objects are allowed to interact with which object members and how they
    interact with them.

    > So if you want to satisfy your boss, show him how the
    > call to "protected" member leads to an exception. He
    > should get happy. :)

    <snip>

    Until the next programmer comes along and shows him:-

    try {
    var goodBoy = new myClass();
    goodBoy.messenger('Hi!');
    }
    catch(e) {
    alert(e.message);
    }

    try {
    goodBoy.messenger.call({utils:goodBoy.utils}, 'Hi xxx!');
    goodBoy.utils.messenger('Hi yyy xxx!');
    ({messenger:goodBoy.utils.messenger}).messenger('Hi mmm xxx!');
    }
    catch(e) {
    alert(e.message);
    }

    - and he sees that your notion of 'protected' means 'wide open'. It is
    easy to execute these 'protected' methods with any arbitrary object as
    their - this - object.

    It may be beyond your comprehension but emulations of access modifiers
    are available that do genuinely restrict access, so this hollow sham of
    yours really doesn't deserve any consideration at all.

    But still, you give us an insight into why you are not interested in
    learning to be good at web development. You are actually in the business
    of trying to impress people who don't know any better, and not really in
    programming at all.

    Richard.
    Richard Cornford, Nov 27, 2005
    #4
  5. Kevin Prichard

    RobG Guest

    Re: Protected static members, abstract classes, object compositionvs. subclassing

    Richard Cornford wrote:
    > Kevin Prichard wrote:
    >
    >>I've recently been following the object-oriented techiques
    >>discussed here and have been testing them for use in a web
    >>application. There is problem that I'd like to discuss with
    >>you experts.

    >
    >
    > This is such a massive subject that I am a little included to let it go.



    I'm glad you didn't, thanks :)


    [...]


    --
    Rob
    RobG, Nov 28, 2005
    #5
  6. RobG <> writes:

    > Richard Cornford wrote:
    >> Kevin Prichard wrote:
    >>
    >>>I've recently been following the object-oriented techiques
    >>>discussed here and have been testing them for use in a web
    >>>application. There is problem that I'd like to discuss with
    >>>you experts.

    >> This is such a massive subject that I am a little included to let it
    >> go.

    >
    >
    > I'm glad you didn't, thanks :)


    So am I. Thank you for the enlightenment!

    Arnaud
    Arnaud Diederen, Nov 28, 2005
    #6
  7. Kevin Prichard

    VK Guest

    Richard Cornford wrote:
    > - and he sees that your notion of 'protected' means 'wide open'. It is
    > easy to execute these 'protected' methods with any arbitrary object as
    > their - this - object.



    This is what I said:
    <quot>
    It means that protected/private/static/final stuff in them is not a
    bulletproof lock but merely an "inconvenience protection" (like locking

    context menu on the page). You always can study the code and/or spoof
    the constructor.
    </quot>

    If you would spend some of your precious time to read it.

    Your beloved closures' tricks is *another* way but *not any better*
    way. The question is only how many startup level users may it stop from
    spoofing constructor. I would say that your {cur{l}ed} way is more
    cryptic but it's really a discussion whos code obfuscator is more
    reliable (the real answer is: none of any).

    Also:
    try - catch - finally and throw are parts of JavaScript / JScript for
    forever (by Internet time scale) and any modern browser supports it
    including Opera 8.x

    Prehistoric and beta models (Opera 6.x, Netscape 3.x, Netscape 6.x,
    Safari 1.x etc) are not subject of my preoccupation in the mean of
    "make it work". But the startup block in the script should let them die
    peacefully. Nevertheless I'm not post each line of code here as a
    turn-key solution with the startup block and roll-back pages.
    VK, Nov 28, 2005
    #7
  8. Kevin Prichard

    VK Guest

    Richard Cornford wrote:
    > try {
    > var goodBoy = new myClass();
    > goodBoy.messenger('Hi!');
    > }
    > catch(e) {
    > alert(e.message);
    > }
    >
    > try {
    > goodBoy.messenger.call({utils:goodBoy.utils}, 'Hi xxx!');
    > goodBoy.utils.messenger('Hi yyy xxx!');
    > ({messenger:goodBoy.utils.messenger}).messenger('Hi mmm xxx!');
    > }
    > catch(e) {
    > alert(e.message);
    > }


    Actually... having read you post once again I'm missing the point of
    your exaltation.

    myClassUtils constructor is minded to be "protected" - not "private".
    These are all different categories (depending of course of the school).

    For me "protected" means that I cannot obtain an instance of such class
    independently but only as a part of a super-imposed class (myClass in
    this case).

    So I don't see how the use of goodBoy which is a legal instance of
    myClass may prove anything in the concern of the "protected" status.

    "private" means that a particular member is accessible only to the
    privileged object members - in the most common case to public object
    members. So in the listed case we want to make
    myClass.utils.messenger() to be accessible only to members of myClass.
    It is more tricky because despite argument.callee.caller gives us the
    actual caller, we cannot simply ask to caller "Who's your master?"
    because the caller has no clue itself at that time ("incontinence of
    [this]") But you can check against some caller's feature to see if it's
    a valid caller. I left the final solution open so the relevant block is
    commented out. The first idea would be to use Java's object
    id-stamping. Thus each new instance get's an unique ID and you stamp
    all members which this ID:

    this.foo = /*public*/ function() {};
    this.foo.oID = newID;

    this.bar = /*private*/ function() {};
    this.bar.oID = newID;

    and then later in bar:

    if (arguments.callee.caller.oID = (arguments.callee.oID) {
    // legal call
    }
    else {
    throw new Error("Attempt to access private member out of the object
    scope");
    }

    I'm not saying this is a final solution and in any case it still
    doesn't guarantee a buletproof protection as I said in the original
    post.
    VK, Nov 28, 2005
    #8
  9. Kevin Prichard

    VK Guest

    VK wrote:
    > if (arguments.callee.caller.oID = (arguments.callee.oID) {
    > // legal call
    > }


    Need to buy a new keyboard - keys are steeking. Of course:

    if (arguments.callee.caller.oID == (arguments.callee.oID)
    VK, Nov 28, 2005
    #9
  10. VK wrote:

    > if (arguments.callee.caller.oID == (arguments.callee.oID)

    ^^^^^^
    This is still not standards compliant. It is possible to be used in a
    well-defined host environment where either JavaScript or JScript are
    available, not on the Web. E.g. Opera 8.51 implements no such property.


    PointedEars
    Thomas 'PointedEars' Lahn, Nov 28, 2005
    #10
  11. VK wrote:
    > Richard Cornford wrote:
    >> try {
    >> var goodBoy = new myClass();
    >> goodBoy.messenger('Hi!');
    >> }
    >> catch(e) {
    >> alert(e.message);
    >> }
    >>
    >> try {
    >> goodBoy.messenger.call({utils:goodBoy.utils}, 'Hi xxx!');
    >> goodBoy.utils.messenger('Hi yyy xxx!');
    >> ({messenger:goodBoy.utils.messenger}).messenger('Hi mmm xxx!');
    >> }
    >> catch(e) {
    >> alert(e.message);
    >> }

    >
    > Actually... having read you post once again I'm missing the
    > point of your exaltation.
    >
    > myClassUtils constructor is minded to be "protected" - not
    > "private". These are all different categories (depending of
    > course of the school).


    Protected is public to some (selected) objects and private to others.
    With different languages applying different criteria to deciding who can
    see what, and when.

    > For me


    This will be good.

    > "protected" means that I cannot obtain an instance of such
    > class independently but only as a part of a super-imposed
    > class (myClass in this case).


    So nothing related to the meaning of the term in any programming
    language?

    > So I don't see how the use of goodBoy which is a legal
    > instance of myClass may prove anything in the concern
    > of the "protected" status.


    Your protected method could be called with any object as its - this -
    object. If the function were a getter it would get for any object, if a
    setter it would set for any object, and if it acted it would act for any
    object.

    > "private" means that a particular member is accessible only
    > to the privileged object members - in the most common case
    > to public object members. So in the listed case we want to
    > make myClass.utils.messenger() to be accessible only to members
    > of myClass.


    Well, the object design is stupidly elaborated for no reason, but if you
    insist.

    > It is more tricky because despite argument.callee.caller
    > gives us the actual caller,


    Or not, in ECMAScript, where no - caller - property is defined.

    > we cannot simply ask to caller "Who's your master?"
    > because the caller has no clue itself at that time


    As there may be no caller it could not be asked anything. But otherwise
    this is incoherent.

    > ("incontinence of [this]")


    This is another manifestations of your general misconception of
    javascript. The - this - keyword has well-defined and constantly
    implemented meaning, your problems with it stem from your not
    understanding javascript and nothing else.

    > But you can check against some caller's feature to see if
    > it's a valid caller. I left the final solution open so the
    > relevant block is commented out. The first idea would be to
    > use Java's object id-stamping. Thus each new instance get's
    > an unique ID and you stamp all members which this ID:


    Unnecessary as objects have distinct identity that can be verified.

    > this.foo = /*public*/ function() {};
    > this.foo.oID = newID;
    >
    > this.bar = /*private*/ function() {};
    > this.bar.oID = newID;


    You silly sod. Verification with a shared secret, and then making the
    secret a public property of the objects so that it is not secret at all.
    What a waste of effort! If you cannot apply better analysis to the
    problem than this you are wasting everyone's time commenting on the
    subject at all (although that goes for the vast majority of your posts
    anyway).

    > and then later in bar:
    >
    > if (arguments.callee.caller.oID = (arguments.callee.oID) {

    ^ ^
    An assignment operator instead of comparison and unbalanced parenthesise
    making this a syntax error?

    > // legal call
    > }
    > else {
    > throw new Error("Attempt to access private member out of the object
    > scope");
    > }


    OK. That is actually less effective than your first attempt (even if the
    errors were corrected).

    > I'm not saying this is a final solution


    I don't know, if your problem is only convincing people who don't know
    any better this will do as well as the first.

    > and in any case it still doesn't guarantee a buletproof
    > protection as I said in the original post.


    No, it isn't. But the question is not whether you are incapable of
    implementing an effective emulation of 'protected' (in some meaningful
    sense of the term) in javascript (obviously that if far beyond you), but
    rather whether it can be done.

    Having determined whether or not it can be done it becomes possible to
    give an informed consideration as to whether it should be done (would
    the overheads and authoring effort be justified by the result?). But
    holding up a sequence of hollow imitations of some form of 'protection'
    do not contribute at all to an understanding of the subject.

    Richard.
    Richard Cornford, Nov 29, 2005
    #11
  12. VK wrote:
    > Richard Cornford wrote:
    >> - and he sees that your notion of 'protected' means 'wide open'.
    >> It is easy to execute these 'protected' methods with any
    >> arbitrary object as their - this - object.

    >
    >
    > This is what I said:
    > <quot>
    > It means that protected/private/static/final stuff in them is
    > not a bulletproof lock but merely an "inconvenience protection"
    > (like locking
    >
    > context menu on the page). You always can study the code and/or
    > spoof the constructor.
    > </quot>


    Yes, it is an irrelevance to the subject of access modifiers.

    > If you would spend some of your precious time to read it.


    I read it, but it just reminded me that you never let not knowing what
    you are talking about prevent you from making a pointless noise.

    > Your beloved closures' tricks is *another* way but *not any
    > better* way.


    Given that you are incapable of comprehending closures you are not
    really in a good position to judge. What you proposed, apart from only
    being functional on a limited number of implementations, fails to
    control access to anything, while closures really can. Reasonable people
    would consider the difference between effective and ineffective when
    applying the label 'better'.

    > The question is only how many startup level users may it
    > stop from spoofing constructor.


    You really don't get it do you?

    > I would say that your {cur{l}ed} way is more cryptic but
    > it's really a discussion whos code obfuscator is more
    > reliable (the real answer is: none of any).


    There is no effort to obfuscate. Any apparent obfuscation is a feature
    of your perception, as anything beyond your comprehension is bound to
    seem obscure. Access modifiers, and particularly the nation of
    'protected', are about _controlling_ which objects have access to which
    properties of which object. That is, imposing those restrictions, and so
    controlling how an object can be used.

    > Also:
    > try - catch - finally and throw are parts of JavaScript /
    > JScript for forever (by Internet time scale)


    What relevance does support for try-catch have to anything that I said?

    > and any modern browser supports it
    > including Opera 8.x


    Even opera 5 supported try-catch, what is your point?

    > Prehistoric and beta models (Opera 6.x, Netscape 3.x,
    > Netscape 6.x, Safari 1.x etc) are not subject of my
    > preoccupation in the mean of "make it work". But the
    > startup block in the script should let them
    > die peacefully.


    When you say 'die peacefully' you actually mean error-out. Which is the
    biggest demonstration of incompetence an author of Internet browser
    scripts can make. Graceful degradation requires that scripts do not
    error-out, but instead actively decide not to act where they are not
    supported.

    > Nevertheless I'm not post each line of code here
    > as a turn-key solution with the startup block and
    > roll-back pages.


    No, you posted enough to show an overly elaborate method of not
    achieving anything useful, or anything at all on any but a couple of
    browsers. So up to your usual standards.

    Richard.
    Richard Cornford, Nov 29, 2005
    #12
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. DaKoadMunky
    Replies:
    4
    Views:
    537
    Lee Weiner
    Apr 20, 2004
  2. JFCM
    Replies:
    4
    Views:
    5,720
  3. Sideswipe
    Replies:
    6
    Views:
    366
    Daniel Pitts
    Sep 20, 2007
  4. Replies:
    3
    Views:
    120
    Jörg W Mittag
    Jan 25, 2008
  5. aidy
    Replies:
    11
    Views:
    203
    Robert Dober
    Jul 22, 2008
Loading...

Share This Page