inheriting statics

classic Classic list List threaded Threaded
29 messages Options
12
Reply | Threaded
Open this post in threaded view
|

inheriting statics

Peter Hall-2
What was the rationale when deciding not to inherit static members?

http://developer.mozilla.org/es4/spec/chapter_9_classes.html#static_methods


Peter

Reply | Threaded
Open this post in threaded view
|

Re: inheriting statics

Nicolas Cannasse
> What was the rationale when deciding not to inherit static members?
>
> http://developer.mozilla.org/es4/spec/chapter_9_classes.html#static_methods

It's actually pretty logical. Since inheritance does not apply to static
members, giving an access to them through subclasses make people
misunderstand what's really a static.

See "The Class Duality" part in haXe Typesystem documentation :
http://haxe.org/doc/types


Nicolas

Reply | Threaded
Open this post in threaded view
|

Re: inheriting statics

Peter Hall-2
"Since inheritance does not apply to static members"

Your assumption is what I was questioning. Why doesn't inheritance
apply to static members?


Peter


On 1/7/07, Nicolas Cannasse <[hidden email]> wrote:

> > What was the rationale when deciding not to inherit static members?
> >
> > http://developer.mozilla.org/es4/spec/chapter_9_classes.html#static_methods
>
> It's actually pretty logical. Since inheritance does not apply to static
> members, giving an access to them through subclasses make people
> misunderstand what's really a static.
>
> See "The Class Duality" part in haXe Typesystem documentation :
> http://haxe.org/doc/types
>
>
> Nicolas
>

Reply | Threaded
Open this post in threaded view
|

Re: inheriting statics

zwetan-3
On 1/7/07, Peter Hall <[hidden email]> wrote:
> "Since inheritance does not apply to static members"
>
> Your assumption is what I was questioning. Why doesn't inheritance
> apply to static members?
>
>

statics are defined on the class itself not the instances of this class
so when you inheriting you can not access static members trough
the instance, only throught the class

but within your classes definition, you can access static members
trough the scope chain


all is pretty well explained in the Flex2 doc

Programming ActionScript 3.0 / Object-Oriented Programming in
ActionScript / Inheritance
then look at the examples for
Static properties not inherited
and
Static properties and the scope chain


I know only one special case where a static member is used for inheritance,
it's the static var prototype :)

quoting the doc
"...
This property is static in that it is specific to the class or
function that you create. For example, if you create a class, the
value of the prototype property is shared by all instances of the
class and is accessible only as a class property. Instances of your
class cannot directly access the prototype property.
"


cheers,
zwetan

Reply | Threaded
Open this post in threaded view
|

Re: inheriting statics

Brendan Eich-2
In reply to this post by Peter Hall-2
On Jan 7, 2007, at 9:50 AM, Peter Hall wrote:

> "Since inheritance does not apply to static members"
>
> Your assumption is what I was questioning. Why doesn't inheritance
> apply to static members?

Right, the assumption should be justified.  One rationale is by  
extension of ES1-3 (plain ol' JS):

function SpecialString(s) { this.value = s; }
SpecialString.prototype = new String;
SpecialString.prototype.toString = function () { return this.value; }
s = new SpecialString("hello");
t = s.charCodeAt(3);
alert(t);
alert(SpecialString.fromCharCode(t));

The last line throws TypeError: SpecialString.fromCharCode is not a  
function.

Inclusion of statics in the scope chain within instance methods is a  
convenience afforded by the new special form of methods defined via  
function definitions nested in a class definition. But it's not  
inheritance.

/be


Reply | Threaded
Open this post in threaded view
|

Re: inheriting statics

Brendan Eich-2
In reply to this post by zwetan-3
On Jan 7, 2007, at 11:10 AM, zwetan wrote:

> quoting the doc
> "...
> This property is static in that it is specific to the class or
> function that you create. For example, if you create a class, the
> value of the prototype property is shared by all instances of the
> class and is accessible only as a class property. Instances of your
> class cannot directly access the prototype property.
> "

This seems misleading to me, since the "value of the prototype  
property" is an object that is not shared as if it were a static  
property value. Instead, the properties of the static prototype  
property are visible in all instances, unless overridden  
("shadowed").  So prototype is not an exception to the rule that  
static properties are not inherited by instances -- it's a different  
animal.

Also, function prototypes are not "static" in any sense (the proposed  
Function.apply static method is a class static in ES4; Date.parse is  
a static method in ES1-4; but Function.prototype is the prototype of  
the Function class/constructor -- it's different from f1.prototype  
and f2.prototype for two functions f1 and f2). Function prototypes  
are "instance variables" of each particular function object.

(I'm nit-picking the AS3 doc just so this doesn't get copied into the  
ES4 spec :-/.)

/be


Reply | Threaded
Open this post in threaded view
|

Re: inheriting statics

P T Withington
In reply to this post by Brendan Eich-2
On 2007-01-07, at 14:32 EST, Brendan Eich wrote:

> On Jan 7, 2007, at 9:50 AM, Peter Hall wrote:
>
>> "Since inheritance does not apply to static members"
>>
>> Your assumption is what I was questioning. Why doesn't inheritance
>> apply to static members?
>
> Right, the assumption should be justified.  One rationale is by  
> extension of ES1-3 (plain ol' JS):

[...]

> Inclusion of statics in the scope chain within instance methods is  
> a convenience afforded by the new special form of methods defined  
> via function definitions nested in a class definition. But it's not  
> inheritance.

One could still ask, "should _classes_ inherit static properties of  
their superclass?"  Should the statics of my superclass be in my  
scope chain?  Should statics of an instance's superclass be visible  
in the instance's constructor?

class Foo {
   static const ZOT = 42;

   function zotValue() {
     return this.constructor.ZOT;
   }
}

class Bar extends Foo {
   function improvedZotValue() {
     return this.constructor.ZOT + 1;
   }
}



Reply | Threaded
Open this post in threaded view
|

Re: inheriting statics

Brendan Eich-2
On Jan 7, 2007, at 12:23 PM, P T Withington wrote:

>> Inclusion of statics in the scope chain within instance methods is  
>> a convenience afforded by the new special form of methods defined  
>> via function definitions nested in a class definition. But it's  
>> not inheritance.
>
> One could still ask, "should _classes_ inherit static properties of  
> their superclass?"

Yes, you're right that classes are not functions -- hence f.prototype  
is an instance property of each function object f, not a static of an  
(unnamed, varargs-type-parameterized?) Function subclass magically  
created "backstage" for f's function definition, and f.prototype is  
not of course the same object as Function.prototype.

So adding classes creates choice for the designer about static  
inheritance and scope. I'll defer to Jeff or Ed to speak to the AS3  
design goals and experience.

>   Should the statics of my superclass be in my scope chain?

Define "my".

>   Should statics of an instance's superclass be visible in the  
> instance's constructor?
>
> class Foo {
>   static const ZOT = 42;
>
>   function zotValue() {
>     return this.constructor.ZOT;
>   }
> }
>
> class Bar extends Foo {
>   function improvedZotValue() {
>     return this.constructor.ZOT + 1;
>   }
> }

Is this use-case important in your experience?  The sketch here does  
not need to abstract away from Foo or Bar via this.constructor, but  
perhaps you have an example motivating such abstraction?

/be

Reply | Threaded
Open this post in threaded view
|

Re: inheriting statics

zwetan-3
In reply to this post by Brendan Eich-2
On 1/7/07, Brendan Eich <[hidden email]> wrote:

> On Jan 7, 2007, at 11:10 AM, zwetan wrote:
>
> > quoting the doc
> > "...
> > This property is static in that it is specific to the class or
> > function that you create. For example, if you create a class, the
> > value of the prototype property is shared by all instances of the
> > class and is accessible only as a class property. Instances of your
> > class cannot directly access the prototype property.
> > "
>
> This seems misleading to me, since the "value of the prototype
> property" is an object that is not shared as if it were a static
> property value. Instead, the properties of the static prototype
> property are visible in all instances, unless overridden
> ("shadowed").  So prototype is not an exception to the rule that
> static properties are not inherited by instances -- it's a different
> animal.
>

agreed, that's a little misleading from the doc, but as I said
it's one special case I could think of :).

Maybe it's because I'm too biased toward the way
ES3 is working, but not inheriting static make perfect sens to me.

I always saw ES3 closer to the objects,
and for statics I just consider them as slot attached to an object
and not part of the inheritance chain (either prototype or traits),
even if the object is a class definition it's still an object.



> Also, function prototypes are not "static" in any sense (the proposed
> Function.apply static method is a class static in ES4; Date.parse is
> a static method in ES1-4; but Function.prototype is the prototype of
> the Function class/constructor -- it's different from f1.prototype
> and f2.prototype for two functions f1 and f2). Function prototypes
> are "instance variables" of each particular function object.
>
> (I'm nit-picking the AS3 doc just so this doesn't get copied into the
> ES4 spec :-/.)
>

the AS3 doc is quite good imho, but still could be improved on
what someone may call "advanced subjects": the relation between
prototype chain and traits chain, the order of lookup for inheritance,
etc.
the kind of subject that if you dealt with ES3 and then start to learn ES4
should be ok to follow, but if you just start with ES4 could be hard
to fully understand.

tricky ex:
if you declare a property in the prototype, and redefine it from an instance,
does the shared property get redefined at the prototype level or
instance level ?

class Blah
    {
    prototype.shared = "hello world";

    function Blah() {}

    }

test1:Blah = new Blah();
test2:Blah = new Blah();
test1.shared = "bonjour le monde";
trace( test2.shared ); // ???

for someone knowing how prototype works in ES3 it can be easy,
but if you didn't dealt with object-based / prototype-based language before
hehe class ain't gonna help you to understand that ;)

and going on, now that you know that it is redefined at the instance level
how could you make it work at the prototype/shared level ?

class Blah
    {
    prototype.shared = "hello world";

    function Blah() {}

    public function change( value:String ):void
        {
        this.constructor.prototype.shared = value;
        }

    }

oh so that means that I can actually define a read-write property
shared by all my instances ?

class Blah
    {
    prototype.shared = "hello world";

    function Blah() {}

    public function set shared( value:String ):void
        {
        this.constructor.prototype.shared = value;
        }

    public function get shared():String
        {
        return prototype.shared;
        }

    }

test1:Blah = new Blah();
test2:Blah = new Blah();
trace( test1.shared ); //hello world
trace( test2.shared ); //hello world
test1.shared = "bonjour le monde";
trace( test2.shared ); // bonjour le monde

but wait that can also be done with a static

class Blah
    {
    private static var _shared:String = "hello world";

    function Blah() {}

    public function set shared( value:String ):void
        {
        _shared = value;
        }

    public function get shared():String
        {
        return _shared;
        }

    }

test1:Blah = new Blah();
test2:Blah = new Blah();
trace( test1.shared ); //hello world
trace( test2.shared ); //hello world
test1.shared = "bonjour le monde";
trace( test2.shared ); // bonjour le monde


sorry for the lengthy and boring examples,
but simply put about static and prototype and inheritance etc...

it should be really helpfull imho to start now to find real use case examples
that can show the real differences, why favour prototype over statics
for sharing
data between instances, or why not

I think people who gonna want to use ES4 and seeing only its class-based nature
will have question as "why still use the prototype, what can I do with
prototype that I can not do with static/class/etc. ?"

zwetan

Reply | Threaded
Open this post in threaded view
|

Re: inheriting statics

P T Withington
In reply to this post by Brendan Eich-2
On 2007-01-07, at 15:53 EST, Brendan Eich wrote:

> On Jan 7, 2007, at 12:23 PM, P T Withington wrote:
>
>>> Inclusion of statics in the scope chain within instance methods  
>>> is a convenience afforded by the new special form of methods  
>>> defined via function definitions nested in a class definition.  
>>> But it's not inheritance.
>>
>> One could still ask, "should _classes_ inherit static properties  
>> of their superclass?"
>
> Yes, you're right that classes are not functions -- hence  
> f.prototype is an instance property of each function object f, not  
> a static of an (unnamed, varargs-type-parameterized?) Function  
> subclass magically created "backstage" for f's function definition,  
> and f.prototype is not of course the same object as  
> Function.prototype.
>
> So adding classes creates choice for the designer about static  
> inheritance and scope. I'll defer to Jeff or Ed to speak to the AS3  
> design goals and experience.
>
>>   Should the statics of my superclass be in my scope chain?
>
> Define "my".

I my sketch below, should methods of Bar have ZOT in their scope  
chain?  Should I be able to write:

class Bar extends Foo {
   function improvedZotValue() {
     return ZOT + 1;
   }
}

and have ZOT resolve to Foo.ZOT?

>>   Should statics of an instance's superclass be visible in the  
>> instance's constructor?
>>
>> class Foo {
>>   static const ZOT = 42;
>>
>>   function zotValue() {
>>     return this.constructor.ZOT;
>>   }
>> }
>>
>> class Bar extends Foo {
>>   function improvedZotValue() {
>>     return this.constructor.ZOT + 1;
>>   }
>> }
>
> Is this use-case important in your experience?  The sketch here  
> does not need to abstract away from Foo or Bar via  
> this.constructor, but perhaps you have an example motivating such  
> abstraction?

My motivation is to keep the door open for a mix-in, where the  
superclass(es) could be different for different concrete classes.  
But it also would make refactoring easier if I could move a static  
property to a different superclass and not have to update all uses of  
it in subclasses.


Reply | Threaded
Open this post in threaded view
|

Re: inheriting statics

Peter Hall-2
> But it also would make refactoring easier if I could move a static
> property to a different superclass and not have to update all uses of
> it in subclasses.
>

So there's a use-case for inheriting static members. Not a hugely
impressive one, but a use-case nonetheless.


The case for inheriting statics:

1. static members are inherited in Java and C# (I think)
2. It won't break existing code because that code either would be in
error or else would have  overridden the member.
3. easier refactoring, if you move the member within an inheritance chain.

The case against inheriting statics:

1. Static members are not inherited in ES3 or JS1
2. It's a change to what's in the spec already



One thing that I do feel strongly about is the scoping of super-class
statics in sub-classes. I find that behaviour confusing, as it feels a
bit like inheritence, but it isn't. What is the value of that
behaviour?

Peter

Reply | Threaded
Open this post in threaded view
|

Re: inheriting statics

Neil Mix
> The case for inheriting statics:
>
> 1. static members are inherited in Java and C# (I think)
> 2. It won't break existing code because that code either would be in
> error or else would have  overridden the member.
> 3. easier refactoring, if you move the member within an inheritance  
> chain.

IIRC static data members in Java are inherited but cannot be  
overridden, which may provide a bit of a catch-22 for #1 and #2?

Reply | Threaded
Open this post in threaded view
|

RE: inheriting statics

Francis Cheng
In reply to this post by Brendan Eich-2
Just to allay Brendan's fears, I can guarantee that this won't be copied
into the ES4 spec. This quote is from the AS3 language reference
documentation for the Object class, and is not from the AS3 language
specification. I'll make sure the Adobe documentation gets fixed.

Francis

-----Original Message-----
From: [hidden email]
[mailto:[hidden email]] On Behalf Of Brendan Eich
Sent: Sunday, January 07, 2007 11:40 AM
To: zwetan
Cc: [hidden email]
Subject: Re: inheriting statics

On Jan 7, 2007, at 11:10 AM, zwetan wrote:

> quoting the doc
> "...
> This property is static in that it is specific to the class or
> function that you create. For example, if you create a class, the
> value of the prototype property is shared by all instances of the
> class and is accessible only as a class property. Instances of your
> class cannot directly access the prototype property.
> "

This seems misleading to me, since the "value of the prototype  
property" is an object that is not shared as if it were a static  
property value. Instead, the properties of the static prototype  
property are visible in all instances, unless overridden  
("shadowed").  So prototype is not an exception to the rule that  
static properties are not inherited by instances -- it's a different  
animal.

Also, function prototypes are not "static" in any sense (the proposed  
Function.apply static method is a class static in ES4; Date.parse is  
a static method in ES1-4; but Function.prototype is the prototype of  
the Function class/constructor -- it's different from f1.prototype  
and f2.prototype for two functions f1 and f2). Function prototypes  
are "instance variables" of each particular function object.

(I'm nit-picking the AS3 doc just so this doesn't get copied into the  
ES4 spec :-/.)

/be

_______________________________________________
Es4-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es4-discuss


Reply | Threaded
Open this post in threaded view
|

Re: inheriting statics

Peter Hall-2
In reply to this post by Neil Mix
> IIRC static data members in Java are inherited but cannot be
> overridden, which may provide a bit of a catch-22 for #1 and #2?
>


Good point. If there is a reason why Java disallows inherited statics
to be overridden then that reason is likely applicable and a decent
enough rationale for not inheriting statics at all in ES4...

Peter

Reply | Threaded
Open this post in threaded view
|

Re: inheriting statics

P T Withington
On 2007-01-09, at 04:52 EST, Peter Hall wrote:

>> IIRC static data members in Java are inherited but cannot be
>> overridden, which may provide a bit of a catch-22 for #1 and #2?
>
> Good point. If there is a reason why Java disallows inherited statics
> to be overridden then that reason is likely applicable and a decent
> enough rationale for not inheriting statics at all in ES4...

But is there a reason?  Or does Java do that just because C++ did that?

Dylan permits members on class, each-subclass, and instance.  They  
are all inherited (and all visible through the instance):

http://www.opendylan.org/books/drm/Slots#MARKER-9-629

Subclasses and instances can give different values to class slots:

http://www.opendylan.org/books/drm/ 
Instance_Creation_and_Initialization#MARKER-9-677

(See "Initialization of Class Allocated Slots")

Reply | Threaded
Open this post in threaded view
|

Re: inheriting statics

Dave Herman-2
In reply to this post by Peter Hall-2
>> IIRC static data members in Java are inherited but cannot be
>> overridden, which may provide a bit of a catch-22 for #1 and #2?

Are we sure? I tried the following in Java 5:

// --
public class C1 { public static int foo = 10; }
public class C2 extends C1 { public static int foo = 1000; }
public class Main {
     public static void main(String[] args) {
         C2 x = new C2();
         System.out.println(x.foo);
         System.out.println(((C1)x).foo);
         System.out.println(((C2)x).foo);
     }
}
// --

and it compiled, ran, and printed:

1000
10
1000

In other words, statics are inherited and can be redefined, although
they are statically resolved, so they have shadowing semantics (like
instance fields) rather than overriding.

Dave

Reply | Threaded
Open this post in threaded view
|

Re: inheriting statics

Peter Hall-2
>
> In other words, statics are inherited and can be redefined, although
> they are statically resolved, so they have shadowing semantics (like
> instance fields) rather than overriding.
>


So there does not even need to be a requirement that the type of
static variables be related to the type of the variable in the
super-class, or for static method signatures to match.

But I'm wondering..

class A {
 public static function foo (){
 }
}

class B extends A {
   // should this non-static method be allowed?
   public function foo(){
       // and, if so, can I do this?
       super.foo();
   }
}

class C extends B {
  public static function foo(){
      // and, if so, would this invoke A.foo or be an error?
      super.foo();
  }
}


Peter

Reply | Threaded
Open this post in threaded view
|

Re: inheriting statics

Neil Mix
In reply to this post by Dave Herman-2
> In other words, statics are inherited and can be redefined,  
> although they are statically resolved, so they have shadowing  
> semantics (like instance fields) rather than overriding.

Yes, but it still means that you can't emulate Java's behavior  
without breaking backward compatibility. Thus, if I'm understanding  
correctly, no matter how you slice it one of Peter's list of 3  
advantages won't hold.

For example, modifying your Java example slightly:

public class C1 {
        static int foo = 10;
        void C1() {
        }
       
        void print() {
                System.out.println(this.foo);
        }
}

class C2 extends C1 {
        static int foo = 1000;
}

public class Main {
     public static void main(String[] args) {
         C2 x = new C2();
         x.print();
     }
}

Which will print 10.

Reply | Threaded
Open this post in threaded view
|

RE: inheriting statics

Jeff Dyer
In reply to this post by Peter Hall-2
In AS3 and draft ES4 'super', like 'this', resolves to a value of an
instance type, and so in your example below the static foo in A will not
be found by 'super.foo()'.

And yes, the definition of foo as a static in class A and an instance
method in class B is allowed. In fact, a static and instance definition
in the same class with the same name is allowed. They appear in
different scopes.

Jd

> -----Original Message-----
> From: [hidden email]
[mailto:[hidden email]]

> On Behalf Of Peter Hall
> Sent: Tuesday, January 09, 2007 8:16 AM
> To: Dave Herman
> Cc: Neil Mix; P T Withington; Brendan Eich; Nicolas Cannasse; es4-
> [hidden email]
> Subject: Re: inheriting statics
>
> >
> > In other words, statics are inherited and can be redefined, although
> > they are statically resolved, so they have shadowing semantics (like
> > instance fields) rather than overriding.
> >
>
>
> So there does not even need to be a requirement that the type of
> static variables be related to the type of the variable in the
> super-class, or for static method signatures to match.
>
> But I'm wondering..
>
> class A {
>  public static function foo (){
>  }
> }
>
> class B extends A {
>    // should this non-static method be allowed?
>    public function foo(){
>        // and, if so, can I do this?
>        super.foo();
>    }
> }
>
> class C extends B {
>   public static function foo(){
>       // and, if so, would this invoke A.foo or be an error?
>       super.foo();
>   }
> }
>
>
> Peter
> _______________________________________________
> Es4-discuss mailing list
> [hidden email]
> https://mail.mozilla.org/listinfo/es4-discuss


Reply | Threaded
Open this post in threaded view
|

Re: inheriting statics

zwetan-3
In reply to this post by Neil Mix
> My motivation is to keep the door open for a mix-in, where the
> superclass(es) could be different for different concrete classes.
> But it also would make refactoring easier if I could move a static
> property to a different superclass and not have to update all uses of
> it in subclasses.

but we already got that in ES4/AS3

class A
    {
    static var foobar:String = "foobar";
    ...
    }

class B extend A
    {

   public function test():String
       {
       return foobar; //you can access the static
       }
    }


------------------------

class A
    {
    ...
    }

class B extend A
    {

    static var foobar:String = "foobar"; //you can move its defintion

   public function test():String
       {
       return foobar;
       }
    }

------------------------


so where is the problem really ?


do you want to be able to access the static inherited like that:

trace( A.foobar );

and if class B extend A
trace( B.foobar );
even if static foobar is defined in class A ?

zwetan

12