www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Classes derived from basic type ?

reply Vladimir <Vladimir_member pathlink.com> writes:
Hello All ! 
I'm just studying D and have been impressed with it's features. 
But some of its I can't understand, for example, presence of .sort method. 
I'm wondering, if D have so compicated base types, which in most senses looks  
exactly like classes, why can't I derive my own classes from it ? Is would be 
very useful in meny cases, and I'm remembering meny uses of it for example in 
python. 
Mar 30 2005
next sibling parent "Carlos Santander B." <csantander619 gmail.com> writes:
Vladimir wrote:
 Hello All ! 
 I'm just studying D and have been impressed with it's features. 
 But some of its I can't understand, for example, presence of .sort method. 
 I'm wondering, if D have so compicated base types, which in most senses looks  
 exactly like classes, why can't I derive my own classes from it ? Is would be 
 very useful in meny cases, and I'm remembering meny uses of it for example in 
 python. 
 
 
 

There's no way to do it in D. In D (just like in many other languages) not everything is an object. _______________________ Carlos Santander Bernal
Mar 30 2005
prev sibling parent reply Georg Wrede <georg.wrede nospam.org> writes:
 But some of its I can't understand, for example, presence of .sort
 method. I'm wondering, if D have so compicated base types, which in
 most senses looks exactly like classes, why can't I derive my own
 classes from it ? Is would be very useful in meny cases, and I'm
 remembering meny uses of it for example in python.

While we're at subtleties in a language, this is a golden example of such! A person new to D, looks at things like arrays, and sees .sort methods and other stuff. This leads -- most naturally -- one to think that we have classes here. Skimming the documentation while believing this, only makes a person confused: ehh, how come there's no proper documentation for these classes, where are all these methods, why can't I derive, etc. One does not immediately see that there _are_ no classes here. One only somehow (especially, this being a new language) assumes, that we then may have some new philosophy or new kinds of classes in _this_ language. Such significantly slows down the process of learning. With any bad luck, such misconceptions stay uncorrected for a longer time, and quite a lot learned during that period, gets its fundaments wrong in one's head. In other words, the reader is entertaining a mental model of the language that is not congruent with that of the developers', which leads to unnecessarily complicated mental structures and gymnastics, when trying to "understand" (or even just learn by heart) the properties of the language. Some of these may be very hard to undo, even after one has been told that the original concept was wrong. Even for smart persons, this often happens only after having visited each particular "collateral misconception" separately -- in spite of the fact that with reason one should be able to let the correction "cascade" through all the cases. Old and rooted (mis)conceptions don't die that easily. (Ex. Some people have a hard time quickly using the right name of many months late in the year.) Even if one is able to get the D facts right at the end, what really does stay, is a belief that this is a labyrinthine and complicated language. And full of trip stones. -- Yet another misconception in itself. ---- So, if something looks like A, it should be A and not B. Convenience shortcuts and such are bad *if* they hamper clarity of vision. What I am saying is: in the future we should avoid conveniences that to the uninitiated look like something they aren't.
Apr 09 2005
parent reply Sean Kelly <sean f4.ca> writes:
In article <42581AE6.5070103 nospam.org>, Georg Wrede says...
 But some of its I can't understand, for example, presence of .sort
 method. I'm wondering, if D have so compicated base types, which in
 most senses looks exactly like classes, why can't I derive my own
 classes from it ? Is would be very useful in meny cases, and I'm
 remembering meny uses of it for example in python.

While we're at subtleties in a language, this is a golden example of such! A person new to D, looks at things like arrays, and sees .sort methods and other stuff. This leads -- most naturally -- one to think that we have classes here. Skimming the documentation while believing this, only makes a person confused: ehh, how come there's no proper documentation for these classes, where are all these methods, why can't I derive, etc.

I agree. And the lack of consistency between arrays and primitive types in this respect is IMO a bad thing. I would prefer if any function: R func( X val, ... ) Could be called normally: X val; func( val, a, b, c ); Or dotted: val.func( a, b, c ); Even better would be if the compiler saw a class derived from a primitive type: class X : int {} then the primitive type would be interpreted as a wrapper class exposing all the usual operator overloads and such. But this second bit isn't strictly necessary as it would be easy enough to define a template class for this purpose: # class ClassOf(T) { # this( T v ) { val = v; } # T opCast() { return val; } # int opCmp( T v ) { ... } # ... # protected: # T val; # } So primitives could be inherited like so: class MyInt : ClassOf!(int) {} In fact I think I may define a class like this for Ares just to have it around. Sean
Apr 09 2005
next sibling parent reply "Kris" <fu bar.com> writes:
"Sean Kelly" <sean f4.ca> wrote in message
news:d39j88$2d2q$1 digitaldaemon.com...
 In article <42581AE6.5070103 nospam.org>, Georg Wrede says...
 But some of its I can't understand, for example, presence of .sort
 method. I'm wondering, if D have so compicated base types, which in
 most senses looks exactly like classes, why can't I derive my own
 classes from it ? Is would be very useful in meny cases, and I'm
 remembering meny uses of it for example in python.

While we're at subtleties in a language, this is a golden example of


A person new to D, looks at things like arrays, and sees .sort methods
and other stuff. This leads -- most naturally -- one to think that we
have classes here.

Skimming the documentation while believing this, only makes a person
confused: ehh, how come there's no proper documentation for these
classes, where are all these methods, why can't I derive, etc.

I agree. And the lack of consistency between arrays and primitive types

 respect is IMO a bad thing.   I would prefer if any function:

 R func( X val, ... )

 Could be called normally:

 X val;
 func( val, a, b, c );

 Or dotted:

 val.func( a, b, c );

 Even better would be if the compiler saw a class derived from a primitive

 class X : int {}

 then the primitive type would be interpreted as a wrapper class exposing

 usual operator overloads and such.

 But this second bit isn't strictly necessary as it would be easy enough to
 define a template class for this purpose:

 # class ClassOf(T) {
 #     this( T v ) { val = v; }
 #     T opCast() { return val; }
 #     int opCmp( T v ) { ... }
 #     ...
 # protected:
 #     T val;
 # }

 So primitives could be inherited like so:

 class MyInt : ClassOf!(int) {}

 In fact I think I may define a class like this for Ares just to have it

 Sean

It would indeed be very nice were D to cleanly support an ability for adding further 'properties' to primitives (in a manner similar to C#, as Andy(?) once noted) - Kris
Apr 09 2005
parent reply pragma <pragma_member pathlink.com> writes:
In article <d39pkv$313k$1 digitaldaemon.com>, Kris says...
"Sean Kelly" <sean f4.ca> wrote in message
 class MyInt : ClassOf!(int) {}

 In fact I think I may define a class like this for Ares just to have it

 Sean

It would indeed be very nice were D to cleanly support an ability for adding further 'properties' to primitives (in a manner similar to C#, as Andy(?) once noted)

Would something like this work? http://www.prowiki.org/wiki4d/wiki.cgi?Typedef-Block - EricAnderton at yahoo
Apr 11 2005
next sibling parent Sean Kelly <sean f4.ca> writes:
In article <d3e93k$2tco$1 digitaldaemon.com>, pragma says...
In article <d39pkv$313k$1 digitaldaemon.com>, Kris says...
"Sean Kelly" <sean f4.ca> wrote in message
 class MyInt : ClassOf!(int) {}

 In fact I think I may define a class like this for Ares just to have it

 Sean

It would indeed be very nice were D to cleanly support an ability for adding further 'properties' to primitives (in a manner similar to C#, as Andy(?) once noted)

Would something like this work? http://www.prowiki.org/wiki4d/wiki.cgi?Typedef-Block

Yes :) This is an excellent proposal for how to implement this feature. Sean
Apr 11 2005
prev sibling parent reply Vladimir <kv11111 mail.ru> writes:
pragma wrote:
 Would something like this work?
 http://www.prowiki.org/wiki4d/wiki.cgi?Typedef-Block

It seems good, but in my opinion typedef-blocks and structs are too similar to exists as different constructs. If we allow struct inheritance by means of just adding base struct members to the front of child struct, and allow struct inheritance from basic types it would solve the problem. Casting child struct to base struct can be allowed, but all struct methods must be treated as non-virtual, so we can keep compitability with C structs. Examples: // analog for typedef int MyInt struct MyInt: int {} // ( super is just shortcat for cast(int*)this ) struct SmartInt: int { public SmartInt opPos(){ // change opPos into an absolute-value operator if(*super < 0) return(-*this); return(*this); } } // static array // ( using template syntax ) struct AutoSumIntArray(N): int[N] { private int _sum = 0; int sum() { return _sum; } int opIndexAssign(int val, int idx) { _sum -= (*super)[idx]; (*super)[idx] = val; _sum += (*super)[idx]; } int opSliceAssign(...) { ... } } // dynamic array // must use class syntax becouse of reference semantic class BoundedIntDynArray: int[] { int bound = 100; this(int l) { if(l > bound) assert(0); super(l); } void length(int l) { if(l > bound) assert(0); super.length = l; } } -- Vladimir
Apr 12 2005
next sibling parent reply pragma <pragma_member pathlink.com> writes:
In article <d3g3c6$2576$1 digitaldaemon.com>, Vladimir says...
pragma wrote:
 Would something like this work?
 http://www.prowiki.org/wiki4d/wiki.cgi?Typedef-Block

It seems good, but in my opinion typedef-blocks and structs are too similar to exists as different constructs. If we allow struct inheritance by means of just adding base struct members to the front of child struct, and allow struct inheritance from basic types it would solve the problem. Casting child struct to base struct can be allowed, but all struct methods must be treated as non-virtual, so we can keep compitability with C structs. Examples: // analog for typedef int MyInt struct MyInt: int {} // ( super is just shortcat for cast(int*)this ) struct SmartInt: int { public SmartInt opPos(){ // change opPos into an absolute-value operator if(*super < 0) return(-*this); return(*this); } } // static array // ( using template syntax ) struct AutoSumIntArray(N): int[N] { private int _sum = 0; int sum() { return _sum; } int opIndexAssign(int val, int idx) { _sum -= (*super)[idx]; (*super)[idx] = val; _sum += (*super)[idx]; } int opSliceAssign(...) { ... } } // dynamic array // must use class syntax becouse of reference semantic class BoundedIntDynArray: int[] { int bound = 100; this(int l) { if(l > bound) assert(0); super(l); } void length(int l) { if(l > bound) assert(0); super.length = l; } } -- Vladimir

This could work, but the only problem is that you loose implicit casting since the memory footprint of some of your examples are not the same as the underlying type. But then again, you'd have to use the typedef explicitly (casting and whatnot) to get the functionality you need, so I guess there's little difference. This way you get shorthand-templating for 'free' which is a huge plus. (use of 'super' is nice too) As long as you get to inherit the base scalar's operators and properties, I honestly don't care which style makes it through. Its too useful a construct not to have. :) - EricAnderton at yahoo
Apr 12 2005
parent Vladimir <kv11111 mail.ru> writes:
pragma wrote:
Examples:
// analog for typedef int MyInt
struct MyInt: int {}

//  ( super is just shortcat for cast(int*)this )
struct SmartInt: int {
    public SmartInt opPos(){ // change opPos into an absolute-value
    operator
        if(*super < 0) return(-*this);
        return(*this);
    }
}

// static array
//  ( using template syntax )
struct AutoSumIntArray(N): int[N] {
    private int _sum = 0;
    int sum() { return _sum; }
    int opIndexAssign(int val, int idx) {
        _sum -= (*super)[idx];
        (*super)[idx] = val;
        _sum += (*super)[idx];
    }
    int opSliceAssign(...) { ... }
}

// dynamic array
//   must use class syntax becouse of reference semantic
class BoundedIntDynArray: int[] {
    int bound = 100;
    this(int l) {
        if(l > bound) assert(0);
        super(l);
    }
    void length(int l) {
        if(l > bound) assert(0);
        super.length = l;
    }
}

This could work, but the only problem is that you loose implicit casting since the memory footprint of some of your examples are not the same as the underlying

 type.  But then again, you'd have to use the typedef explicitly (casting
 and whatnot) to get the functionality you need, so I guess there's little
 difference.  This way you get shorthand-templating for 'free' which is a
 huge plus. (use of 'super' is nice too)
 
 As long as you get to inherit the base scalar's operators and properties,
 I
 honestly don't care which style makes it through.  Its too useful a
 construct not to have. :)

-- Vladimir
Apr 13 2005
prev sibling parent reply Stewart Gordon <smjg_1998 yahoo.com> writes:
Vladimir wrote:
<snip>
 If we allow struct inheritance by means of just adding base struct members
 to the front of child struct, and allow struct inheritance from basic types
 it would solve the problem.
 Casting child struct to base struct can be allowed, but all struct methods
 must be treated as non-virtual, so we can keep compitability with C
 structs.
 
 Examples:
 // analog for typedef int MyInt
 struct MyInt: int {}
 
 //  ( super is just shortcat for cast(int*)this )
 struct SmartInt: int {
     public SmartInt opPos(){ // change opPos into an absolute-value operator
         if(*super < 0) return(-*this);
         return(*this);
     }
 }

This is like an idea that I thought of, though on existing structs/unions rather than primitive types. Under my idea, the derived type would be a union rather than a struct. This is because with the way D works, it doesn't make so much sense to add data members - since structs have value semantics, increasing the size means that it isn't really a value of the base type anymore. OTOH it does make a bit of sense to add methods and/or views of the data to an existing struct (such as one defined in an external API). But I guess this idea could work on built-in types as well.... Stewart. -- My e-mail is valid but not my primary mailbox. Please keep replies on the 'group where everyone may benefit.
Apr 20 2005
parent Vladimir <kv11111 mail.ru> writes:
Stewart Gordon wrote:
 Vladimir wrote:
 <snip>
 If we allow struct inheritance by means of just adding base struct
 members to the front of child struct, and allow struct inheritance from
 basic types it would solve the problem.
 Casting child struct to base struct can be allowed, but all struct
 methods must be treated as non-virtual, so we can keep compitability with
 C structs.
 
 Examples:
 // analog for typedef int MyInt
 struct MyInt: int {}
 
 //  ( super is just shortcat for cast(int*)this )
 struct SmartInt: int {
     public SmartInt opPos(){ // change opPos into an absolute-value
     operator
         if(*super < 0) return(-*this);
         return(*this);
     }
 }

This is like an idea that I thought of, though on existing structs/unions rather than primitive types. Under my idea, the derived type would be a union rather than a struct. This is because with the way D works, it doesn't make so much sense to add data members - since structs have value semantics, increasing the size means that it isn't really a value of the base type anymore.

what situation size difference could cause a problem ?
 OTOH 
 it does make a bit of sense to add methods and/or views of the data to
 an existing struct (such as one defined in an external API).

 
 But I guess this idea could work on built-in types as well....
 
 Stewart.
 

-- Vladimir
Apr 21 2005
prev sibling parent xs0 <xs0 xs0.com> writes:
 But this second bit isn't strictly necessary as it would be easy enough to
 define a template class for this purpose:
 
 # class ClassOf(T) {
 #     this( T v ) { val = v; }
 #     T opCast() { return val; }
 #     int opCmp( T v ) { ... }
 #     ...
 # protected:
 #     T val;
 # }
 
 So primitives could be inherited like so:
 
 class MyInt : ClassOf!(int) {}
 
 In fact I think I may define a class like this for Ares just to have it around.

Hmm, wouldn't a struct fit better, because of value semantics? It should be much faster, too, because there's no "this" and virtual function dereferencing going on.. OTOH, you can't derive structs, afaik, so it may not be a good thing to do in a template. You could probably mixin stuff, though; having a template with all the usual operators, and being able to add new stuff should be ok, I guess (for a silly example, it may be dangerous to have a type that behaves like an int with all the operators, except that if you divide it by 5 it formats your hard drive? What if you forget it does that? :) xs0
Apr 10 2005