[OpenLayers-Dev] 2.10 and 2.11-RC1 OpenLayers.Class behavior changes

Richard Didier didier.richard at ign.fr
Tue Jul 26 03:41:56 EDT 2011


Le lundi 25 juillet 2011 23:39:50, Andreas Hocevar a écrit :
> Hi Didier,
> 
> So what you implemented with your overload method results in the same as if
> you'd simply use OpenLayers.Class:
> 
> A = A.overload(A, {
>     initialize:function() {
>         this.p_= "A.initialize-new";
>         OpenLayers.Console.info(this.p_);
>     },
>     pa:"PA-new"
> });
> 
> is equivalent to
> 
> A = OpenLayers.Class(A, {
>     initialize:function() {
>         this.p_= "A.initialize-new";
>         OpenLayers.Console.info(this.p_);
>     },
>     pa:"PA-new"
> });
> 
> The problem here is that A becomes a subclass of itself. So what you could
> try instead to avoid this is
> 

That's the reason why I have written OpenLayers.overload to avoid this problem. In OL 2.10, it is ok (the classes 
tree remains perfect). In OL 2.11, the classes tree is broken ... I would like to understand why this method works 
in OL 2.10 and not in OL 2.11 !(

> A = OpenLayers.Class(OpenLayers.Util.applyIf({
>     initialize:function() {
>         this.p_= "A.initialize-new";
>         OpenLayers.Console.info(this.p_);
>     },
>     pa:"PA-new"
> }, A));
> 

I guess OpenLayers.Util.applyIf is to be written based on extend/applyDefaults ?

> But either way, I wonder why you do this in the first place, instead of
> creating subclasses with your modifications.
> 

The rational is many fold :

1/ There are tickets for the next OL release that we incorporate directly in our production scripts. Usually, we try 
to push fixes every three months and a new release a month or two after a new OL release;

2/ We insert patches directly in the OL classes tree (for instance, our GeoDRM mechanism or bugs reported by 
users) and allow users to still use OL's API but patched !

3/ The OL library is split into several functional "ready to use" libraries like : hooks to our JS library allowing 
developpers to use whatever OL they want or GeoExt or ... Another example is to forge a library without vector 
stuffs in, another to have mobile things, another to have a small OL wrapper to talk with Flash, and so on ... For 
doing that, we apply patches/overlay depending on the functionnality we aim at.

The key issue is not to change OL API (Classes), possibly add new methods to OL API. For functionnalities not in 
OL (mainly controlers), we have our own namespace.

didier

> Andreas.
> 
> On Jul 25, 2011, at 22:05 , RICHARD Didier wrote:
> >> Hi Didier,
> > 
> > Hi Andreas,
> > 
> >> what I showed you in the last snippet is exactly what happens in
> >> OpenLayers.Class. So to do it the way we recommend, and if you're into
> >> anonymous functions, you could do something like the following, which is
> >> 100% OpenLayers API compliant:
> >> 
> >> var X = OpenLayers.Class({
> >> 
> >>    initialize: function() {
> >>    
> >>        this._p = "A.initialize";
> >>        OpenLayers.Console.info(this._p);
> >>    
> >>    },
> >>    ma: function() {
> >>    
> >>        OpenLayers.Console.info(this._p);
> >>    
> >>    }
> >> 
> >> });
> >> var x1 = new (OpenLayers.Class(X, {
> >> 
> >>    initialize: function() {
> >>    
> >>        this._p = "A.initialize-new";
> >>        OpenLayers.Console.info(this.p_);
> >>    
> >>    }
> >> 
> >> }));
> > 
> > I have tested something like this for my use case :
> > 
> > A= OpenLayers.Class({...});
> > A.B= OpenLayers.Class(A, {...});
> > 
> > A= OpenLayers.Class(A, { ...});
> > var a= new A(); //ok
> > var ab= new AB(); //ko: A.B is not a constructor ...
> > 
> > My idea was just to overwrite part of a class path and have it propagated
> > ...
> > 
> > I have this working in OL 2.10 (based on your snippet):
> >    /**
> >    
> >     * Function: OpenLayers.overload
> >     * Apply the patch to the given class and propagate it downward
> >     * to the sub-classes by insuring that only not overwritten
> >     * methods() or properties are overloaded.
> >     *
> >     * Parameters:
> >     * P - {Object} an instance of {<OpenLayers.Class>}
> >     * F - {Object} an object used to overwrite methods (including
> >     * constructor) and properties of P and its sub-classes.
> >     *
> >     * Returns:
> >     * {Object} the overloaded instance of given class.
> >     */
> >    
> >    OpenLayers.overload= function(P,F) {
> >    
> >        //save old class
> >        var X= P;
> >        var xProto= OpenLayers.Util.extend({},P.prototype);
> >        var f= OpenLayers.Util.extend({},F);
> >        
> >        if (typeof(F.initialize)=="function") {
> >        
> >            // protect initializer from sub-classes overloading :
> >            var pProto= P.prototype;
> >            pProto.initialize= function() {
> > 
> > F.initialize.apply(this,arguments); };
> > 
> >            delete f["initialize"];
> >            OpenLayers.Util.extend(pProto,f);
> >            P= pProto.initialize;
> >            P.prototype= pProto;
> >        
> >        } else {
> >        
> >            OpenLayers.Util.extend(P.prototype, f);
> >        
> >        }
> >        
> >        // restore sub-classes:
> >        // propagate constructor/properties/method to sub-class ...
> >        for (var xn in X) {
> >        
> >            var p= X[xn];
> >            delete X[xn];
> >            if (typeof(p)=='function' && p.prototype.initialize) {//ensure
> > 
> > it is a Class
> > 
> >                f= OpenLayers.Util.extend({},F);
> >                // check for overloaded properties :
> >                for (var fn in F) {
> >                
> >                    var fp= F[fn];
> >                    if (typeof(fp)=="function") {
> >                    
> >                        if (p.prototype[fn]===xProto[fn]) {
> >                        
> >                            // override method ...
> >                            continue;
> >                        
> >                        }
> >                        delete f[fn];
> >                        continue;
> >                    
> >                    }
> >                    if (p.prototype.hasOwnProperty(fn) &&
> > 
> > X.prototype.hasOwnProperty(fn) && fp!==undefined) {
> > 
> >                        if (p.prototype[fn]===xProto[fn]) {
> >                        
> >                            // override property ...
> >                            continue;
> >                        
> >                        }
> >                        delete f[fn];
> >                        continue;
> >                    
> >                    }
> >                
> >                }
> >                // override sub-class :
> >                var x= p;
> >                var c= OpenLayers.Class(P,p.prototype);
> >                OpenLayers.Util.extend(c,x);
> >                P[xn]= OpenLayers.overload(c,f);
> >            
> >            } else {
> >            
> >                P[xn]= p;
> >            
> >            }
> >        
> >        }
> >        xProto= null;
> >        X= null;
> >        
> >        return P;
> >    
> >    };
> > 
> > The classes tree is the one I sent yesterday:
> >    A= OpenLayers.Class({
> >    
> >        initialize:function() { this.p_= "A.initialize";
> > 
> > OpenLayers.Console.info(this.p_); },
> > 
> >        pa:"PA",
> >        p_:null,
> >        ma:function() { OpenLayers.Console.info("A.ma="+this.pa); }
> >    
> >    });
> >    A.B= OpenLayers.Class(A,{
> >    
> >        pa:"PA-bis",
> >        pb:"PB",
> >        mb:function() { OpenLayers.Console.info("B.mb="+this.pa+"
> > 
> > "+this.pb); }
> > 
> >    });
> >    A.B.D= OpenLayers.Class(A.B,{
> >    
> >        initialize:function() { this.p_= "D.initialize";
> > 
> > OpenLayers.Console.info(this.p_); }
> > 
> >    });
> >    A.B.E= OpenLayers.Class(A.B,{
> >    
> >        initialize:function() { this.p_= "E.initialize";
> > 
> > OpenLayers.Console.info(this.p_); }
> > 
> >    });
> >    A.C= OpenLayers.Class(A,{
> >    
> >        initialize:function() { this.p_= "C.initialize";
> > 
> > OpenLayers.Console.info(this.p_); },
> > 
> >        pc:"PC",
> >        ma:function() { OpenLayers.Console.info("C.ma="+this.pa+"
> > 
> > "+this.pc); }
> > 
> >    });
> >    A.C.F= OpenLayers.Class(A.C,{
> >    
> >        pf:"PF",
> >        mf:function() { OpenLayers.Console.info("F.mf="+this.pa+"
> > 
> > "+this.pc+" "+this.pf); }
> > 
> >    });
> >    A.C.G= OpenLayers.Class(A.C,{
> >    
> >        pg:"PG",
> >        ma:function() { OpenLayers.Console.info("G.ma="+this.pa+"
> > 
> > "+this.pc+" "+this.pg); }
> > 
> >    });
> > 
> > and then :
> >    A= OpenLayers.overload(A, {
> >    
> >        initialize:function() { this.p_= "A.initialize-new";
> > 
> > OpenLayers.Console.info(this.p_); },
> > 
> >        pa:"PA-new"
> >    
> >    });
> > 
> > to overload the classes tree ...
> > 
> > The same method "almost works" in OL 2.11 except that in the end, I have
> > got all sub-classes in the root, and so on recursively :
> > 
> > A
> > 
> >  B
> >  
> >    B
> >    C
> >    D
> >    E
> >  
> >  C
> >  
> >    F
> >    
> >      F
> >      G
> >    
> >    G
> >  
> >  D
> >  E
> > 
> > (again, in OL 2.10, everything looks good in the end)
> > 
> > I may be in the wrong path to solve my problem ...
> > 
> > Any thoughts ?
> > 
> >> Andreas.
> > 
> > didier
> > 
> > _______________________________________________
> > Dev mailing list
> > Dev at lists.osgeo.org
> > http://lists.osgeo.org/mailman/listinfo/openlayers-dev

-- 
RICHARD Didier - Chef du pôle technique du Géoportail
2/4, avenue Pasteur - 94165 Saint Mandé Cedex
Tél : +33 (0) 1 43 98 83 23


More information about the Dev mailing list