Thread overview
Access violation with interface as key type
Sep 29, 2005
Xenon
Sep 29, 2005
Xenon
Sep 29, 2005
Holger
Sep 29, 2005
Xenon
Sep 29, 2005
Derek Parnell
Sep 30, 2005
Thomas Kühne
Sep 30, 2005
Mike Parker
Sep 30, 2005
Xenon
September 29, 2005
I see no reason why this code should not work. However, it consistently crashes on execution. Compiled with >dmd bug.d -ofbug.exe

interface A {
int x();
}

class B : A {
int x() {
return 1;
}
}

int main(char[][] args) {
B foo = new B();

int[B] arrayB;
arrayB[foo] = 1; // this works
printf("Ok B\n");

int[A] arrayA;
arrayA[foo] = 1; // Error: Access Violation
printf("Ok A\n");

return 0;
}

If I define A as an abstract class instead, changing the declaration to

abstract class A {
abstract int x();
}

the example works as expected. Is this a bug, or a strange "feature"?


September 29, 2005
In article <dhffam$12jr$1@digitaldaemon.com>, Xenon says...
>I see no reason why this code should not work. However, it consistently crashes on execution. Compiled with >dmd bug.d -ofbug.exe

I forgot to mention; version 0.133 on Windows.


September 29, 2005
In article <dhffam$12jr$1@digitaldaemon.com>, Xenon says...
>
>I see no reason why this code should not work. However, it consistently crashes on execution. Compiled with >dmd bug.d -ofbug.exe
>
>interface A {
>int x();
>}
>
>class B : A {
>int x() {
>return 1;
>}
>}
>
>int main(char[][] args) {
>B foo = new B();
>
>int[B] arrayB;
>arrayB[foo] = 1; // this works
>printf("Ok B\n");
>
>int[A] arrayA;
>arrayA[foo] = 1; // Error: Access Violation
>printf("Ok A\n");
>
>return 0;
>}
>
>If I define A as an abstract class instead, changing the declaration to
>
>abstract class A {
>abstract int x();
>}
>
>the example works as expected. Is this a bug, or a strange "feature"?
>

I'm not sure if it is a bug, at least it is a known issue. Perhaps someone more knowledgeable could shed a light on this?

Cheers,
Holger


September 29, 2005
In article <dhgd66$1qsq$1@digitaldaemon.com>, Holger says...
>I'm not sure if it is a bug, at least it is a known issue. Perhaps someone more knowledgeable could shed a light on this?

Maybe the real bug is that the compiler doesn't produce an error in this situation, but generates incorrect (segfaulting) code instead? It should be trivial to check whether the key type is an interface and display an appropriate message.


September 29, 2005
Xenon wrote:
> In article <dhgd66$1qsq$1@digitaldaemon.com>, Holger says...
> 
>>I'm not sure if it is a bug, at least it is a known issue.
>>Perhaps someone more knowledgeable could shed a light on this?
> 
> 
> Maybe the real bug is that the compiler doesn't produce an error in this
> situation, but generates incorrect (segfaulting) code instead? It should be
> trivial to check whether the key type is an interface and display an appropriate
> message.
> 
> 
I've also had similar problems with interfaces. They seem to be broken. I really hope Walter is someday able to allow similar interfaces that they do have in Java.

I think the problem is that D seems to handle interfaces and classes as separate structures.
September 29, 2005
On Fri, 30 Sep 2005 02:12:06 +0300, Jari-Matti Mäkelä wrote:

> Xenon wrote:
>> In article <dhgd66$1qsq$1@digitaldaemon.com>, Holger says...
>> 
>>>I'm not sure if it is a bug, at least it is a known issue. Perhaps someone more knowledgeable could shed a light on this?
>> 
>> Maybe the real bug is that the compiler doesn't produce an error in this situation, but generates incorrect (segfaulting) code instead? It should be trivial to check whether the key type is an interface and display an appropriate message.
>> 
> I've also had similar problems with interfaces. They seem to be broken. I really hope Walter is someday able to allow similar interfaces that they do have in Java.
> 
> I think the problem is that D seems to handle interfaces and classes as separate structures.

Excuse my Java/C# ignorance, but in my mind interfaces and classes are two very different beasts. I view interfaces to be no more than a hinting mechanism for the compiler so it can verify that all the required methods for a class have been declared. Plus it can supply a default implementation if one is required.

However, the way I see people trying to use interfaces in D leads me to suspect that these people assume that interfaces are really a type of class; a subset in some way maybe. Kind of like a light weight class, but I can't quite grok what this concept of an interface is. The way they are documented in D seems logical and simple to understand and use.

To me an array of interfaces is weird. It's like asking for an array of typedefs (not an array of the new data type but of the typedef itself).

I've read stuff on the interface concept in Java and I still don't quite get it. Maybe someone here can enlighten me by not speaking in Java jargon (that is, straight forward English instead).

-- 
Derek
(skype: derek.j.parnell)
Melbourne, Australia
30/09/2005 9:40:32 AM
September 30, 2005
Derek Parnell schrieb:
> However, the way I see people trying to use interfaces in D leads me to suspect that these people assume that interfaces are really a type of class; a subset in some way maybe. Kind of like a light weight class, but I can't quite grok what this concept of an interface is. The way they are documented in D seems logical and simple to understand and use.
> 
> To me an array of interfaces is weird. It's like asking for an array of typedefs (not an array of the new data type but of the typedef itself).
> 
> I've read stuff on the interface concept in Java and I still don't quite get it. Maybe someone here can enlighten me by not speaking in Java jargon (that is, straight forward English instead).

There are at least 2 common uses for interfaces:

*** sample A ***
class Snake {}
class Car {}

Both classes are abstract representations of moving objects, thus the use of an interface to get the current speed

interface ObjectInMotion {
	uint getCurrentSpeed();
}

class Snake : ObjectInMotion { .... }
class Car : ObjectInMotion { .... }

does make sense, whereas a common base class is sometimes to restrictive.

*** sample B ***
Integrating closed source classes into an existing framework often
requires the use of interfaces.

class ClosedSource {
	int membercount();
}

class Frame {
	int getTotalNumberOfMembers();
}

Let's integrate the ClosedSource class into our framework:

interface IFrame {
	int getTotalNumberOfMembers();
}

class Frame : IFrame { .... }

class Integrated : ClosedSource, IFrame {
	int getTotalNumberOfMembers(){
		return membercount();
	}
}

Thomas
September 30, 2005
Derek Parnell wrote:
> On Fri, 30 Sep 2005 02:12:06 +0300, Jari-Matti Mäkelä wrote:

> However, the way I see people trying to use interfaces in D leads me to
> suspect that these people assume that interfaces are really a type of
> class; a subset in some way maybe. Kind of like a light weight class, but I
> can't quite grok what this concept of an interface is. The way they are
> documented in D seems logical and simple to understand and use.
> 
> To me an array of interfaces is weird. It's like asking for an array of
> typedefs (not an array of the new data type but of the typedef itself).

An array of interfaces makes no sense when you think of it as 'an array interface declarations', but when you think in terms of 'an array of objects that implement a given interface', then it should make sense. When an interface is referenced in code, it's a way of allowing you to access several different implementations of an interface without the need to know the details of the implementation. If ClassA and ClassB are in two seperate class heirarchies, but they both implement MyInterface, then I should be able to manipulate them via a MyInterface reference (which is a reference to an object instance which implements the interface, not the interface itself). By declaring an array of MyInterfaces, or an aa with MyInterface keys, I should be able to use instances of ClassA and ClassB as members of the array or as aa keys and expect to be able to call MyInterface methods on them. An interface is another way to 'view' a class which implements it.

Another way to look at it is to consider the two basic types of inheritance: implementation inheritance and interface inheritance. C++ makes no distiction between the two, but C++ programmers make a distinction by referring to interface classes as 'pure virtual'. The Java designers decided that multiple inheritance is a Really Bad Thing when you inherit the implementation, but is acceptable when inheriting the interface. So the 'interface' type was created to enforce the distinction between interface inheritance and implementation inheritance. If you equate an 'interface' with a 'pure virtual' C++ class, you should start to see why D interfaces appear broken in some regards.
September 30, 2005
Mike Parker wrote:
> An array of interfaces makes no sense when you think of it as 'an array interface declarations', but when you think in terms of 'an array of objects that implement a given interface', then it should make sense. When an interface is referenced in code, it's a way of allowing you to access several different implementations of an interface without the need to know the details of the implementation. If ClassA and ClassB are in two seperate class heirarchies, but they both implement MyInterface, then I should be able to manipulate them via a MyInterface reference (which is a reference to an object instance which implements the interface, not the interface itself). By declaring an array of MyInterfaces, or an aa with MyInterface keys, I should be able to use instances of ClassA and ClassB as members of the array or as aa keys and expect to be able to call MyInterface methods on them. An interface is another way to 'view' a class which implements it.
> 
> Another way to look at it is to consider the two basic types of inheritance: implementation inheritance and interface inheritance. C++ makes no distiction between the two, but C++ programmers make a distinction by referring to interface classes as 'pure virtual'. The Java designers decided that multiple inheritance is a Really Bad Thing when you inherit the implementation, but is acceptable when inheriting the interface. So the 'interface' type was created to enforce the distinction between interface inheritance and implementation inheritance. If you equate an 'interface' with a 'pure virtual' C++ class, you should start to see why D interfaces appear broken in some regards.

This is exactly what I was thinking! Thanks Mike. Maybe Walter thinks that supporting Java-style interfaces is a performance issue. I can't come up with many "good" ways to "emulate" multiple inheritance in D without using interfaces the way Java does. Here's an example:

interface ComponentModel {
	void method();
}

abstract class VisualComponent {
	void draw {
		blaah
	}
}

// just a data structure, not visual
class Implementation1: ComponentModel {
	override void method {
		blaah blaah
	}
}

// used in a gui
class Implementation2: VisualComponent, ComponentModel {
	private:
	ComponentModel cm;

	this() {
		cm = new Implementation1();
	}

	void method() { cm.method(); }
}

Now, I can use handy abstract arrays like these:

ComponentModel[] a;
a ~= new Implementation2();
a ~= new Implementation3();
...

a.sort();
findElement(a);
September 30, 2005
In article <dhjcar$1h14$1@digitaldaemon.com>, =?ISO-8859-1?Q?Jari-Matti_M=E4kel=E4?= says...
>This is exactly what I was thinking! Thanks Mike. Maybe Walter thinks that supporting Java-style interfaces is a performance issue.

As I said before, if interfaces are not supported as key types *by intention*, the compiler is supposed to reject my program.

Currently I use the following workaround: I define my array as int[Object], and use cast(Object) on insertion and cast(A) on extraction of a key. This is ugly and a bit error-prone, but otherwise works reasonably well.

I don't see why the compiler couldn't do something similar automatically, but then I have no idea of DMD's internals. The current situation however, which is silently producing code that is garbage, is IMO worse than no support at all.