View mode: basic / threaded / horizontal-split · Log in · Help
May 03, 2012
Class methods in D?
In Windows, you need to register a "window class" before you can actually 
create an instance of it.

Mapping this idea to D (and most other languages, I admit) is hard. 
Microsoft's solution in C# is pretty ugly.

The problem is this:
You make a class like
class Window
{
   HWND handle;
   virtual @property string className()  // How the system identifies this 
subclass
   { /*some default code for lazily registering a class*/ }
   this() { this.handle = className(this.className, ...); }
}
which people are supposed to inherit from.

The trouble is that there is *no clean way* (that I can think of) to ensure 
this:
if (typeid(windowA) == typeid(windowB))
{ assert(windowA.className == windowB.className); }

This is necessary in order to make sure that the idea of a "class" in D is 
the same as the one that the system sees.

If className() was class method, this assumption would be trivial to ensure: 
subclasses could override it, and it would be the same for all instances of 
the class. It would map to OOP in D **VERY** cleanly.
Right now, though, it's a big pain to map this concept... and the lack of 
proper reflection isn't helping.
(Microsoft just decided to make it an instance property, but if you look at 
the code, you'll see it's infinitely ugly...)

Is there any chance that we can get (overridable) class methods in D?
If not, is there a good solution to this problem?
(At least, will it be possible to retrieve the static methods of a class 
with reflection?)
May 03, 2012
Re: Class methods in D?
>    this() { this.handle = className(this.className, ...); }

whoops, typo.

That line should say:
this() { this.handle = CreateWindow(this.className, ...); }
May 03, 2012
Re: Class methods in D?
On Thu, 03 May 2012 13:21:55 -0400, Mehrdad <wfunction@hotmail.com> wrote:

> In Windows, you need to register a "window class" before you can  
> actually create an instance of it.
>
> Mapping this idea to D (and most other languages, I admit) is hard.  
> Microsoft's solution in C# is pretty ugly.
>
> The problem is this:
> You make a class like
> class Window
> {
>     HWND handle;
>     virtual @property string className()  // How the system identifies  
> this subclass
>     { /*some default code for lazily registering a class*/ }
>     this() { this.handle = className(this.className, ...); }
> }
> which people are supposed to inherit from.
>
> The trouble is that there is *no clean way* (that I can think of) to  
> ensure this:
> if (typeid(windowA) == typeid(windowB))
> { assert(windowA.className == windowB.className); }
>
> This is necessary in order to make sure that the idea of a "class" in D  
> is the same as the one that the system sees.
>
> If className() was class method, this assumption would be trivial to  
> ensure: subclasses could override it, and it would be the same for all  
> instances of the class. It would map to OOP in D **VERY** cleanly.
> Right now, though, it's a big pain to map this concept... and the lack  
> of proper reflection isn't helping.
> (Microsoft just decided to make it an instance property, but if you look  
> at the code, you'll see it's infinitely ugly...)
>
> Is there any chance that we can get (overridable) class methods in D?
> If not, is there a good solution to this problem?
> (At least, will it be possible to retrieve the static methods of a class  
> with reflection?)

This works:

import std.stdio;

class A
{
  string name;
  this() {this.name = typeid(this).name;}
}

class B : A {}

void main()
{
   A b = new B;
   A a = new A;
   writefln("A: %s, B: %s", a.name, b.name);
}

outputs:

A: testclassname.A, B: testclassname.B

Do what you want with that name, not sure if the window class can have  
dots in it... (I haven't done much low-level GUI work on windows).

Why does this work?  Because typeid(obj) gets the TypeInfo based on the  
object's *derived* type, not it's static type.  Since the typeinfo is  
properly set before the ctor is called, this means you get the correct  
type.  Also, note if there is anything you need via the TypeInfo, it's  
accessible.  Given the recent additions to the compiler and the RTInfo  
template, you should be able to generate everything you need.

-Steve
May 03, 2012
Re: Class methods in D?
On Thursday, 3 May 2012 at 17:45:20 UTC, Steven Schveighoffer 
wrote:
> This works:
>
> import std.stdio;
>
> class A
> {
>   string name;
>   this() {this.name = typeid(this).name;}
> }
>
> class B : A {}
>
> void main()
> {
>    A b = new B;
>    A a = new A;
>    writefln("A: %s, B: %s", a.name, b.name);
> }
>
> outputs:
>
> A: testclassname.A, B: testclassname.B
>
> -Steve

Oh, but that's only the name!

The trouble is that window classes have a lot of attributes -- 
styles, background brushes, etc. -- that are all shared across 
instances.

There is currently no way (that I know of) to allow a subclass to 
define its own attributes, *without* also giving it a chance to 
define them per-instance instead of per-class.
May 03, 2012
Re: Class methods in D?
On Thu, 03 May 2012 13:48:24 -0400, Mehrdad <wfunction@hotmail.com> wrote:

> On Thursday, 3 May 2012 at 17:45:20 UTC, Steven Schveighoffer wrote:
>> This works:
>>
>> import std.stdio;
>>
>> class A
>> {
>>   string name;
>>   this() {this.name = typeid(this).name;}
>> }
>>
>> class B : A {}
>>
>> void main()
>> {
>>    A b = new B;
>>    A a = new A;
>>    writefln("A: %s, B: %s", a.name, b.name);
>> }
>>
>> outputs:
>>
>> A: testclassname.A, B: testclassname.B
>>
>> -Steve
>
> Oh, but that's only the name!
>
> The trouble is that window classes have a lot of attributes -- styles,  
> background brushes, etc. -- that are all shared across instances.
>
> There is currently no way (that I know of) to allow a subclass to define  
> its own attributes, *without* also giving it a chance to define them  
> per-instance instead of per-class.

There's the RTInfo method I told you about (recently added) if you want to  
stick the information directly into TypeInfo at compile time.

There's also static ctors.  Just add a hashtable based on the class name,  
and use typeid(this).name as the initial key.  You have to handle all the  
inheritance of properties yourself, but that shouldn't be too difficult.

-Steve
May 03, 2012
Re: Class methods in D?
> There's the RTInfo method I told you about (recently added) if 
> you want to stick the information directly into TypeInfo at 
> compile time.
>
> There's also static ctors.  Just add a hashtable based on the 
> class name, and use typeid(this).name as the initial key.  You 
> have to handle all the inheritance of properties yourself, but 
> that shouldn't be too difficult.
>
> -Steve

Ooh... how do I get RTInfo? It's not in druntime/phobos....
May 03, 2012
Re: Class methods in D?
On 03/05/2012 18:21, Mehrdad wrote:
> In Windows, you need to register a "window class" before you can
> actually create an instance of it.

If you are mucking about on 'doze you might find my dubious port of the 
ATL window classes relevant:

http://www.sstk.co.uk/atlWinD.php

That does all that tedious registering of windows classes etc.
I used a static class member IIRC.

I've ripped this off of MS so use at your own risk. ;)

-- 
My enormous talent is exceeded only by my outrageous laziness.
http://www.ssTk.co.uk
May 03, 2012
Re: Class methods in D?
On Thursday, 3 May 2012 at 18:32:18 UTC, Simon wrote:
> On 03/05/2012 18:21, Mehrdad wrote:
>> In Windows, you need to register a "window class" before you 
>> can
>> actually create an instance of it.
>
> If you are mucking about on 'doze you might find my dubious 
> port of the ATL window classes relevant:
>
> http://www.sstk.co.uk/atlWinD.php
>
> That does all that tedious registering of windows classes etc.
> I used a static class member IIRC.
>
> I've ripped this off of MS so use at your own risk. ;)

lol. thanks.
May 03, 2012
Re: Class methods in D?
On Thu, 03 May 2012 14:05:26 -0400, Mehrdad <wfunction@hotmail.com> wrote:

>> There's the RTInfo method I told you about (recently added) if you want  
>> to stick the information directly into TypeInfo at compile time.
>>
>> There's also static ctors.  Just add a hashtable based on the class  
>> name, and use typeid(this).name as the initial key.  You have to handle  
>> all the inheritance of properties yourself, but that shouldn't be too  
>> difficult.
>>
>> -Steve
>
> Ooh... how do I get RTInfo? It's not in druntime/phobos....

https://github.com/D-Programming-Language/druntime/blob/master/import/object.di#L622

Need the github versions of dmd/druntime/phobos.

Basically how it works is the compiler evaluates RTInfo!T where T is the  
type for which TypeInfo is being generated, and places the result into a  
location that is returned by TypeInfo.rtInfo property.  This all happens  
at compile-time, so it effectively gives you a hook to store runtime type  
information into the TypeInfo.

As far as I know, there's not official documentation on it, it's a pretty  
beta feature.  But I think it will open a door to actual runtime type  
information that we never had before.

One limitation is, it has to be inside the runtime, and specifically in  
object.di.  However, we may be able to effectively generate class/struct  
specific runtime type information.  For example:

struct RTTI
{
  // druntime-specified properties
  ...
  // type-specific properties
  void *typeSpecificProperties;
}

template RTInfo_Instance(T)
{
   static if(is(typeof({void *x = T.__rtInfo();}))
     immutable RTTI RTInfo_Instance = RTTI(..., T.__rtInfo());
   else
     immutable RTTI RTInfo_Instance = RTTI(..., null);
}

template RTInfo(T)
{
   immutable void * RTInfo = &RTInfo_Instance!T;
}

I have no idea if this works :)  But I'm *positive* someone with better  
template skills than me can make something like this work.

-Steve
May 03, 2012
Re: Class methods in D?
Oo ok I'll take a look at it, thanks.
« First   ‹ Prev
1 2 3
Top | Discussion index | About this forum | D home