www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Why are interfaces so restrictive?

reply BCS <BCS_member pathlink.com> writes:
Why can only classes implement an interface?

     If I understand correctly, an instance of an interface is a context
pointer 
along with a pointer to a table of function pointers. When a method of an 
interface is called, the function pointer is called with the context pointer as 
the first argument. In effect, it is a delegate using a table of function 
pointers rather than just one.
     Calling a method of a class isn't the only way to get a delegate, they can 
be made from a struct or even a local function, so why not let a struct 
implement an interface or even let a function define an interface literal.

For example:
-------------------

interface Database
{
	Item SerchForItem(char[]);
	bool AddItem(char[], Item);
	bool RemoveItem(char[]);
}

void DatabaseUI(Database);

void Foo()
{
	Item[char[]] bar;

	Database db = interface:Database
	{
		Item SerchForItem(char[] n)
		{
			if(n in bar)
				return bar[n];
			throw new Error("blah!");
		}

		bool AddItem(char[] n, Item i)
		{
			if(n in bar)
				throw new Error("blah!");
			bar[n] = i;
			return true;
		}

		bool RemoveItem(char[] n)
		{
			if(n in bar)
			{
				bar.remove(n);
				return true;
			}
			throw new Error("blah!");
		}
	}

	DatabaseUI(db);

	...
}


---------------------
p.s. Maby there should be a NG for post 1.0 stuff.
Mar 17 2006
parent reply "Jarrett Billingsley" <kb3ctd2 yahoo.com> writes:
"BCS" <BCS_member pathlink.com> wrote in message 
news:dvfm45$1j5f$3 digitaldaemon.com...
 why not let a struct implement an interface

Because that would complicate structs, something that I think Walter is not willing to do.
 or even let a function define an interface literal..

You could define an anonymous class literal which implemented that interface. class Item { } interface Database { Item SearchForItem(char[]); bool AddItem(char[], Item); bool RemoveItem(char[]); } void DatabaseUI(Database deebs) { } void Foo() { DatabaseUI(new class Database { Item[char[]] bar; Item SearchForItem(char[] n) { if(n in bar) return bar[n]; throw new Error("blah!"); } bool AddItem(char[] n, Item i) { if(n in bar) throw new Error("blah!"); bar[n] = i; return true; } bool RemoveItem(char[] n) { if(n in bar) { bar.remove(n); return true; } throw new Error("blah!"); } }); } void main() { }
Mar 17 2006
parent reply BCS <BCS_member pathlink.com> writes:
In article <dvfoqe$29i$1 digitaldaemon.com>, Jarrett Billingsley says...
"BCS" <BCS_member pathlink.com> wrote in message 
news:dvfm45$1j5f$3 digitaldaemon.com...
 why not let a struct implement an interface

Because that would complicate structs, something that I think Walter is not willing to do.

No it wouldn't (if my understanding of interfaces is correct) all that it would require is the generation of the function pointer table at compile time and at run time, the joining of that pointer and a pointer to the struct.
 or even let a function define an interface literal..

You could define an anonymous class literal which implemented that interface.

That might work, however, it requires allocating a class and a more complicated call/access sequence. Either the class has to have access to the local stack frame (by storing a pointer to it and adding another level of indirection) or the data in the class needs to be available to the function (again by way of a pointer). Nether of these is desirable and the same effect can be had (with less cost) by using my idea.
class Item
{

}

interface Database
{
 Item SearchForItem(char[]);
 bool AddItem(char[], Item);
 bool RemoveItem(char[]);
}

void DatabaseUI(Database deebs)
{

}


void Foo()
{
 DatabaseUI(new class Database
 {
  Item[char[]] bar;

  Item SearchForItem(char[] n)
  {
   if(n in bar)
    return bar[n];
   throw new Error("blah!");

  }

  bool AddItem(char[] n, Item i)
  {
   if(n in bar)
    throw new Error("blah!");

   bar[n] = i;
   return true;
  }

  bool RemoveItem(char[] n)
  {
   if(n in bar)
   {
    bar.remove(n);
    return true;
   }

   throw new Error("blah!");
  }
 });
}

void main()
{

} 

Mar 17 2006
parent reply "Jarrett Billingsley" <kb3ctd2 yahoo.com> writes:
"BCS" <BCS_member pathlink.com> wrote in message 
news:dvfqn0$470$1 digitaldaemon.com...
 No it wouldn't (if my understanding of interfaces is correct) all that it 
 would
 require is the generation of the function pointer table at compile time 
 and at
 run time, the joining of that pointer and a pointer to the struct.

It might be possible, but it would involve making a "second" kind of inheritance that wouldn't really fit into the current class and interface inheritance method.
 That might work, however, it requires allocating a class and a more 
 complicated
 call/access sequence. Either the class has to have access to the local 
 stack
 frame (by storing a pointer to it and adding another level of indirection) 
 or
 the data in the class needs to be available to the function (again by way 
 of a
 pointer). Nether of these is desirable and the same effect can be had 
 (with less
 cost) by using my idea.

It can. void Foo() { Item[char[]] bar; Database db = new class Database { Item SearchForItem(char[] n) { if(n in bar) return bar[n]; throw new Error("blah!"); } bool AddItem(char[] n, Item i) { if(n in bar) throw new Error("blah!"); bar[n] = i; return true; } bool RemoveItem(char[] n) { if(n in bar) { bar.remove(n); return true; } throw new Error("blah!"); } }; DatabaseUI(db); } This looks strikingly like what you originally posted.
Mar 18 2006
parent reply BCS <BCS_member pathlink.com> writes:
In article <dvh9mr$2nbc$1 digitaldaemon.com>, Jarrett Billingsley says...
"BCS" <BCS_member pathlink.com> wrote in message 
news:dvfqn0$470$1 digitaldaemon.com...
 No it wouldn't (if my understanding of interfaces is correct) all that it 
 would require is the generation of the function pointer table at compile 
 time and at run time, the joining of that pointer and a pointer to the 
 struct.

It might be possible, but it would involve making a "second" kind of inheritance that wouldn't really fit into the current class and interface inheritance method.

Why do we say a class "inherits" from an interface? The only thing it gets is a set of mandatory function signatures and a way of passing them around. Wouldn't it be better to say that something "Implements" an interface? I guess my point is that allowing for the use of interfaces with other things would have some benefits and shouldn't, IMHO, have much cost.
 That might work, however, it requires allocating a class and a more 
 complicated call/access sequence. Either [#1] the class has to have 
 access to the local stack frame (by storing a pointer to it and 
 adding another level of indirection) or [#2] the data in the class 
 needs to be available to the function (again by way of a pointer). 
 Nether of these is desirable and the same effect can be had (with 
 less cost) by using my idea.

It can.

Yep, I agree that would work, however that is method #1 from above, and the access to the array is by way of a pointer stored in the object.
void Foo()
{
 Item[char[]] bar;

 Database db = new class Database
 {
  Item SearchForItem(char[] n)
  {
   if(n in bar)
    return bar[n];
   throw new Error("blah!");

  }

  bool AddItem(char[] n, Item i)
  {
   if(n in bar)
    throw new Error("blah!");

   bar[n] = i;
   return true;
  }

  bool RemoveItem(char[] n)
  {
   if(n in bar)
   {
    bar.remove(n);
    return true;
   }

   throw new Error("blah!");
  }
 };

 DatabaseUI(db);
}

This looks strikingly like what you originally posted. 

Mar 18 2006
next sibling parent Lars Ivar Igesund <larsivar igesund.net> writes:
BCS wrote:

 In article <dvh9mr$2nbc$1 digitaldaemon.com>, Jarrett Billingsley says...
"BCS" <BCS_member pathlink.com> wrote in message
news:dvfqn0$470$1 digitaldaemon.com...
 No it wouldn't (if my understanding of interfaces is correct) all that
 it would require is the generation of the function pointer table at
 compile time and at run time, the joining of that pointer and a pointer
 to the struct.

It might be possible, but it would involve making a "second" kind of inheritance that wouldn't really fit into the current class and interface inheritance method.

Why do we say a class "inherits" from an interface? The only thing it gets is a set of mandatory function signatures and a way of passing them around. Wouldn't it be better to say that something "Implements" an interface?

Well, in Java it is called "implements", like class Foo implements Serializable { } but in C++, interfaces are only structs/classes without any implementations, that is all methods like this void foo() = 0; and then there is no difference between normal inheritance and implementing these interfaces. But of course, "implements" would in general be the proper term.
Mar 18 2006
prev sibling parent reply "Jarrett Billingsley" <kb3ctd2 yahoo.com> writes:
"BCS" <BCS_member pathlink.com> wrote in message 
news:dvhh1e$318k$1 digitaldaemon.com...
 [#1] the class has to have
 access to the local stack frame (by storing a pointer to it and
 adding another level of indirection)


the access to the array is by way of a pointer stored in the object.

And how else would you access that array? How would it be done with your method? Your method really just looks like a class.
Mar 18 2006
parent reply BCS <BCS_member pathlink.com> writes:
In article <dvht07$g9u$1 digitaldaemon.com>, Jarrett Billingsley says...
"BCS" <BCS_member pathlink.com> wrote in message 
news:dvhh1e$318k$1 digitaldaemon.com...
 [#1] the class has to have access to the local stack frame 
 (by storing a pointer to it and adding another level of 
 indirection)


the access to the array is by way of a pointer stored in the object.

And how else would you access that array? How would it be done with your method? Your method really just looks like a class.

In the case described, the interface has a context pointer that points to an object, in that object is a pointer to the stack frame of the function that is used to get the array. What I am proposing would be to have the interfaces context pointer point to the stack frame directly. (*(*Object.ptr).frame).array vs. (*frame).array The difference is much like the difference between a delegate made from a class method call and one from a nested function call. Yes, they look a lot alike, but one is a little bit more expensive.
Mar 18 2006
parent reply "Jarrett Billingsley" <kb3ctd2 yahoo.com> writes:
"BCS" <BCS_member pathlink.com> wrote in message 
news:dvhv4i$ip7$1 digitaldaemon.com...
 In the case described, the interface has a context pointer that points to 
 an
 object, in that object is a pointer to the stack frame of the function 
 that is
 used to get the array. What I am proposing would be to have the interfaces
 context pointer point to the stack frame directly.

 (*(*Object.ptr).frame).array

 vs.

 (*frame).array

 The difference is much like the difference between a delegate made from a 
 class
 method call and one from a nested function call.

 Yes, they look a lot alike, but one is a little bit more expensive.

"Nittering" and "nats" come to mind ;) I would imagine that in any case, the compiler would optimize the access to the stack frame, by dereferencing it once and keeping it in a register. Seems more like a QOI issue to me. And kind of a rare, niche issue at that. I mean, how often do you need to do this?
Mar 18 2006
parent BCS <BCS_member pathlink.com> writes:
In article <dvi36k$o4o$1 digitaldaemon.com>, Jarrett Billingsley says...
"BCS" <BCS_member pathlink.com> wrote in message 
 The difference is much like the difference between a delegate made from a 
 class
 method call and one from a nested function call.

 Yes, they look a lot alike, but one is a little bit more expensive.

"Nittering" and "nats" come to mind ;) I would imagine that in any case, the compiler would optimize the access to the stack frame, by dereferencing it once and keeping it in a register. Seems more like a QOI issue to me. And kind of a rare, niche issue at that. I mean, how often do you need to do this?

interface implemented with a struct yesterday.
Mar 18 2006