www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Confused about interfaces in D

reply Thomas Leonard <talex5+d gmail.com> writes:
Hi,

I'm used to interfaces in Java, and I'm wondering why this doesn't work 
in D:

  interface Clock {}

  class SystemClock : Clock {}

  void main(string[] args) {
	Clock c = new SystemClock();
	c.toString();
  }

It says:

  $ dmd clock.d
  clock.d(7): Error: no property 'toString' for type 'clock.Clock'

This compiles, though:

	Clock c = new SystemClock();
	(cast(Object) c).toString();

When is a "Clock" not an "Object"?

Thanks,
Oct 01 2008
next sibling parent reply "Bill Baxter" <wbaxter gmail.com> writes:
On Thu, Oct 2, 2008 at 5:59 AM, Thomas Leonard <talex5+d gmail.com> wrote:
 Hi,

 I'm used to interfaces in Java, and I'm wondering why this doesn't work
 in D:

  interface Clock {}

  class SystemClock : Clock {}

  void main(string[] args) {
        Clock c = new SystemClock();
        c.toString();
  }

 It says:

  $ dmd clock.d
  clock.d(7): Error: no property 'toString' for type 'clock.Clock'

 This compiles, though:

        Clock c = new SystemClock();
        (cast(Object) c).toString();

 When is a "Clock" not an "Object"?
When it's derived from IUnknown, a special case put in to support COM interfaces on Win32. I've not heard anyone voice support for this particular design decision. I suppose it's very convenient if you happen to be a COM programmer, but I'm not sure why a vendor-specific technology like COM should get such special treatment in a language spec. --bb
Oct 01 2008
next sibling parent reply Ary Borenszweig <ary esperanto.org.ar> writes:
Bill Baxter escribió:
 On Thu, Oct 2, 2008 at 5:59 AM, Thomas Leonard <talex5+d gmail.com> wrote:
 Hi,

 I'm used to interfaces in Java, and I'm wondering why this doesn't work
 in D:

  interface Clock {}

  class SystemClock : Clock {}

  void main(string[] args) {
        Clock c = new SystemClock();
        c.toString();
  }

 It says:

  $ dmd clock.d
  clock.d(7): Error: no property 'toString' for type 'clock.Clock'

 This compiles, though:

        Clock c = new SystemClock();
        (cast(Object) c).toString();

 When is a "Clock" not an "Object"?
When it's derived from IUnknown, a special case put in to support COM interfaces on Win32. I've not heard anyone voice support for this particular design decision. I suppose it's very convenient if you happen to be a COM programmer, but I'm not sure why a vendor-specific technology like COM should get such special treatment in a language spec. --bb
Better support a mostly unused specific case, than the broader general case, right? :-(
Oct 01 2008
parent Christopher Wright <dhasenan gmail.com> writes:
Ary Borenszweig wrote:
 Bill Baxter escribió:
 On Thu, Oct 2, 2008 at 5:59 AM, Thomas Leonard <talex5+d gmail.com> 
 wrote:
 Hi,

 I'm used to interfaces in Java, and I'm wondering why this doesn't work
 in D:

  interface Clock {}

  class SystemClock : Clock {}

  void main(string[] args) {
        Clock c = new SystemClock();
        c.toString();
  }

 It says:

  $ dmd clock.d
  clock.d(7): Error: no property 'toString' for type 'clock.Clock'

 This compiles, though:

        Clock c = new SystemClock();
        (cast(Object) c).toString();

 When is a "Clock" not an "Object"?
When it's derived from IUnknown, a special case put in to support COM interfaces on Win32. I've not heard anyone voice support for this particular design decision. I suppose it's very convenient if you happen to be a COM programmer, but I'm not sure why a vendor-specific technology like COM should get such special treatment in a language spec. --bb
Better support a mostly unused specific case, than the broader general case, right? :-(
I've seen a number of issues relating to this -- for instance, tango's Variant had issues with inserting something as an interface and retrieving it as the class: interface IFoo {} class Foo : IFoo {} Variant v = cast(IFoo)new Foo; variant.get!(Foo); // throws VariantTypeMismatchException This was resolved, fortunately, but people will encounter problems relating to this indefinitely.
Oct 01 2008
prev sibling next sibling parent Thomas Leonard <talex5+d gmail.com> writes:
On Thu, 02 Oct 2008 06:12:26 +0900, Bill Baxter wrote:

 On Thu, Oct 2, 2008 at 5:59 AM, Thomas Leonard <talex5+d gmail.com>
 wrote:
 Hi,

 I'm used to interfaces in Java, and I'm wondering why this doesn't work
 in D:

  interface Clock {}

  class SystemClock : Clock {}

  void main(string[] args) {
        Clock c = new SystemClock();
        c.toString();
  }

 It says:

  $ dmd clock.d
  clock.d(7): Error: no property 'toString' for type 'clock.Clock'
 When is a "Clock" not an "Object"?
When it's derived from IUnknown, a special case put in to support COM interfaces on Win32. I've not heard anyone voice support for this particular design decision. I suppose it's very convenient if you happen to be a COM programmer, but I'm not sure why a vendor-specific technology like COM should get such special treatment in a language spec.
Ah, I see. I'm not too worried about COM support, so I edited mtype.c to return MATCHconvert whenever the target is Object. That fixes it for me: http://repo.or.cz/w/delight/core.git?a=commit;h=4e5750a980ef24b65284342f51f549a9d23dc282 Thanks!
Oct 02 2008
prev sibling parent reply Bryan Power <bp2626 yahoo.com> writes:
Bill Baxter wrote:
 
 When it's derived from IUnknown, a special case put in to support COM
 interfaces on Win32.
 I've not heard anyone voice support for this particular design decision.
 I suppose it's very convenient if you happen to be a COM programmer,
 but I'm not sure why a vendor-specific technology like COM should get
 such special treatment in a language spec.
 
 --bb
Steven Schveighoffer wrote:
 The issue is totally with COM.
 
 Without the requirement for any interface to possibly be a COM interface, 
 all interfaces would implicitly inherit from ObjectInterface or some 
 interface that always has the functions required in Object defined (e.g. 
 toString()).
 
But COM objects don't have the same base functions as Object does, so interfaces have no required base functions. Making life difficult for those who never ever work with COM (and I can't say I blame them, COM sucks). -Steve
A fair bit of extended API functionality on Windows is presented via COM. This includes very important API sets like DirectX, which is implemented via COM. A bonus of COM is that it allows use of the API in its OOP form in C++ while still allowing the API to be used in procedural languages like IA32, C and Pascal without any hacks or tricks. Even Mozilla has their own COM implementation. While I admit COM can be messy at times, I use it almost daily for my work, and since I am free to use the languages of my choosing I generally use D. This interface feature allows me to port COM definitions from the C/C++ headers to D seamlessly and quickly: interface IWbemObjectSink : IUnknown {} for example. I am all for the COM compatibility.
Oct 02 2008
next sibling parent "Jarrett Billingsley" <jarrett.billingsley gmail.com> writes:
On Thu, Oct 2, 2008 at 7:36 PM, Bryan Power <bp2626 yahoo.com> wrote:
 Bill Baxter wrote:
 When it's derived from IUnknown, a special case put in to support COM
 interfaces on Win32.
 I've not heard anyone voice support for this particular design decision.
 I suppose it's very convenient if you happen to be a COM programmer,
 but I'm not sure why a vendor-specific technology like COM should get
 such special treatment in a language spec.

 --bb
Steven Schveighoffer wrote:
 The issue is totally with COM.

 Without the requirement for any interface to possibly be a COM interface,
 all interfaces would implicitly inherit from ObjectInterface or some
 interface that always has the functions required in Object defined (e.g.
 toString()).

 But COM objects don't have the same base functions as Object does, so
 interfaces have no required base functions.  Making life difficult for those
 who never ever work with COM (and I can't say I blame them, COM sucks).

 -Steve
A fair bit of extended API functionality on Windows is presented via COM. This includes very important API sets like DirectX, which is implemented via COM. A bonus of COM is that it allows use of the API in its OOP form in C++ while still allowing the API to be used in procedural languages like IA32, C and Pascal without any hacks or tricks. Even Mozilla has their own COM implementation. While I admit COM can be messy at times, I use it almost daily for my work, and since I am free to use the languages of my choosing I generally use D. This interface feature allows me to port COM definitions from the C/C++ headers to D seamlessly and quickly: interface IWbemObjectSink : IUnknown {} for example. I am all for the COM compatibility.
I am as well, but treating it as the general case makes no sense. IUnknown and anything derived from it should be treated as special cases; anything else should be implicitly castable to Object.
Oct 02 2008
prev sibling parent "Bill Baxter" <wbaxter gmail.com> writes:
On Fri, Oct 3, 2008 at 8:42 AM, Jarrett Billingsley
<jarrett.billingsley gmail.com> wrote:
 On Thu, Oct 2, 2008 at 7:36 PM, Bryan Power <bp2626 yahoo.com> wrote:
 Bill Baxter wrote:
 When it's derived from IUnknown, a special case put in to support COM
 interfaces on Win32.
 I've not heard anyone voice support for this particular design decision.
 I suppose it's very convenient if you happen to be a COM programmer,
 but I'm not sure why a vendor-specific technology like COM should get
 such special treatment in a language spec.

 --bb
Steven Schveighoffer wrote:
 The issue is totally with COM.

 Without the requirement for any interface to possibly be a COM interface,
 all interfaces would implicitly inherit from ObjectInterface or some
 interface that always has the functions required in Object defined (e.g.
 toString()).

 But COM objects don't have the same base functions as Object does, so
 interfaces have no required base functions.  Making life difficult for those
 who never ever work with COM (and I can't say I blame them, COM sucks).

 -Steve
A fair bit of extended API functionality on Windows is presented via COM. This includes very important API sets like DirectX, which is implemented via COM. A bonus of COM is that it allows use of the API in its OOP form in C++ while still allowing the API to be used in procedural languages like IA32, C and Pascal without any hacks or tricks. Even Mozilla has their own COM implementation. While I admit COM can be messy at times, I use it almost daily for my work, and since I am free to use the languages of my choosing I generally use D. This interface feature allows me to port COM definitions from the C/C++ headers to D seamlessly and quickly: interface IWbemObjectSink : IUnknown {} for example. I am all for the COM compatibility.
I am as well, but treating it as the general case makes no sense. IUnknown and anything derived from it should be treated as special cases; anything else should be implicitly castable to Object.
Same here. I have nothing against support for COM, just support for COM that complicates the common case for everyone just for the benefit of being able to use COM. I don't think such a compromise is required. But I also don't have an alternate design I can provide. I suspect that along the lines of what Ja-double-r-e-double-t says, there could be a foreign_interface type in D that objects can derive from. IUnknown could be one such foreign_interface. But that may just be making a bad situation worse. I'm pretty sure from looking at the DirectX headers that you can do COM in C++ without any fancy compiler support, so it seems likely that there could be a completely different approach to supporting COM (and other things) in a more general way via mixins and (someday) macros. Or maybe some new compile-time decorator syntax. --bb
Oct 02 2008
prev sibling parent reply ylixir <ylixir gmail.com> writes:
Thomas Leonard wrote:
 Hi,
 
 I'm used to interfaces in Java, and I'm wondering why this doesn't work 
 in D:
 
   interface Clock {}
 
   class SystemClock : Clock {}
 
   void main(string[] args) {
 	Clock c = new SystemClock();
 	c.toString();
   }
 
 It says:
 
   $ dmd clock.d
   clock.d(7): Error: no property 'toString' for type 'clock.Clock'
 
 This compiles, though:
 
 	Clock c = new SystemClock();
 	(cast(Object) c).toString();
 
 When is a "Clock" not an "Object"?
 
 Thanks,
"Clock" is never an "Object". Object is a class every other class is implicitly inherited from, and interfaces cannot be derived from classes, otherwise you would wind up with the nastiness that makes multiple inheritance in c++ such a nightmare (diamond shaped inheritance trees, etc), and would in fact eliminate the need for interfaces altogether. casting c to Object works because SystemClock inherits from Object, without the cast it doesn't work because Clock is not inherited from Object. Maybe i'm missing something, as others seem to be going on about COM programming, but i don't think this has anything to do with COM, it's simply that D doesn't support multiple inheritance, with good reason.
Oct 02 2008
next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
"ylixir" wrote
 Thomas Leonard wrote:
 Hi,

 I'm used to interfaces in Java, and I'm wondering why this doesn't work 
 in D:

   interface Clock {}

   class SystemClock : Clock {}

   void main(string[] args) {
 Clock c = new SystemClock();
 c.toString();
   }

 It says:

   $ dmd clock.d
   clock.d(7): Error: no property 'toString' for type 'clock.Clock'

 This compiles, though:

 Clock c = new SystemClock();
 (cast(Object) c).toString();

 When is a "Clock" not an "Object"?

 Thanks,
"Clock" is never an "Object". Object is a class every other class is implicitly inherited from, and interfaces cannot be derived from classes, otherwise you would wind up with the nastiness that makes multiple inheritance in c++ such a nightmare (diamond shaped inheritance trees, etc), and would in fact eliminate the need for interfaces altogether. casting c to Object works because SystemClock inherits from Object, without the cast it doesn't work because Clock is not inherited from Object. Maybe i'm missing something, as others seem to be going on about COM programming, but i don't think this has anything to do with COM, it's simply that D doesn't support multiple inheritance, with good reason.
The issue is totally with COM. Without the requirement for any interface to possibly be a COM interface, all interfaces would implicitly inherit from ObjectInterface or some interface that always has the functions required in Object defined (e.g. toString()). But COM objects don't have the same base functions as Object does, so interfaces have no required base functions. Making life difficult for those who never ever work with COM (and I can't say I blame them, COM sucks). -Steve
Oct 02 2008
prev sibling parent Ary Borenszweig <ary esperanto.org.ar> writes:
ylixir wrote:
 Thomas Leonard wrote:
 Hi,

 I'm used to interfaces in Java, and I'm wondering why this doesn't 
 work in D:

   interface Clock {}

   class SystemClock : Clock {}

   void main(string[] args) {
     Clock c = new SystemClock();
     c.toString();
   }

 It says:

   $ dmd clock.d
   clock.d(7): Error: no property 'toString' for type 'clock.Clock'

 This compiles, though:

     Clock c = new SystemClock();
     (cast(Object) c).toString();

 When is a "Clock" not an "Object"?

 Thanks,
"Clock" is never an "Object". Object is a class every other class is implicitly inherited from, and interfaces cannot be derived from classes, otherwise you would wind up with the nastiness that makes multiple inheritance in c++ such a nightmare (diamond shaped inheritance trees, etc), and would in fact eliminate the need for interfaces altogether. casting c to Object works because SystemClock inherits from Object, without the cast it doesn't work because Clock is not inherited from Object. Maybe i'm missing something, as others seem to be going on about COM programming, but i don't think this has anything to do with COM, it's simply that D doesn't support multiple inheritance, with good reason.
In Java you can implicitly cast an interface to an Object. This is also can only exist in runtime in the form of a class that implements it. Now you know that every class has Object as a top superclass. Since you can cast any class to Object, and since an interface can only exist in runtime in the form of a class, you can impllicity convert any interface to an Object. This doesn't work in D because there's an interface named IUnknown used to do COM stuff, and classes that implement that interface don't have Object as the top superclass. Tihs breaks my previous "demonostration" (every class has Object as a top superclass).
Oct 02 2008