digitalmars.D - Interface Support: Return Types
- Derek Parnell (81/81) May 30 2005 My experience with Interfaces is zero, except for dabbling with the D
- Sean Kelly (4/10) May 30 2005 Sounds like you want interfaces to support covariant return types. I wa...
- Derek Parnell (11/22) May 30 2005 As I say, I have no real experience with Interfaces, so if 'covariant
- Mike Parker (19/24) May 30 2005 But then doesn't that defeat the purpose of using the interface in the
- Derek Parnell (45/74) May 30 2005 Yep, that makes sense.
- kris (16/122) May 30 2005 If I may add something:
- Mike Parker (50/72) May 30 2005 And this is what I don't understand. Constidering that MutableList
- Derek Parnell (101/192) May 30 2005 Stop there!
- kris (17/32) May 30 2005 Part of the power within Interfaces comes from their agnostic
- Derek Parnell (60/96) May 30 2005 As I say, I *really* am new to all of this Interface stuff. The stuff yo...
- kris (116/229) May 31 2005 Right. If I understand you correctly :)
- Derek Parnell (8/8) May 31 2005 On Tue, 31 May 2005 00:51:21 -0700, kris wrote:
- Walter (24/31) May 31 2005 classes
- Sean Kelly (4/9) May 31 2005 Sounds reasonable. I kind of see interface implementation as a contract...
- Matthias Becker (18/21) Jun 01 2005 Such a vtbl[] coud be created at runtime as well, right? So perhaps ther...
- Sean Kelly (5/26) Jun 01 2005 Cool idea, but this scares me a bit--it allows an object to impersonate
- Andrew Fedoniouk (8/36) Jun 04 2005 I guess you'll find
- Ben Hinkle (6/47) Jun 04 2005 I don't know much about Objective-C but I think it also has a concept ro...
- Kris (8/52) Jun 04 2005 Christopher Diggins was around here for a little while:
- Jarrett Billingsley (6/12) May 30 2005 That's very weird. I always assumed D's interfaces supported covariant
- Walter (23/45) May 31 2005 I can't help but think that an interface template will fit the bill here...
- Derek Parnell (9/38) May 31 2005 I didn't know one could do that! I think I'll update the wiki DocComment...
My experience with Interfaces is zero, except for dabbling with the D offering. My understanding of what interfaces are is that they are a mechanism for defining a set of methods that must be implemented by a class. About 30 minutes ago I was reading the DSource forum in which 'teqdruid' posted an simple example that shocked me into realizing that there is at least one deficiency in the current Interface syntax. Given the interfaces ... interface MutableList { MutableList opSlice(int a, int b); } interface Reproduce { Reproduce dup(); } and then a class based on this interface ... class MyList : MutableList, Reproduce { MutableList opSlice(int a, int b) { . . . } Reproduce dup() { . . . } . . . } This means that the MyList class must implement the interfaces' methods, namely it must define a function called opSlice() that returns a 'MutableList', and function called dup() that must return a 'Reproduce'. However, I would rather have it return a MyList class instead, because as it now stands, to use such a class I must code ... MyList a = new MyList(xx); MyList b; MyList c; b = cast(MyList)a[2 .. 3]; c = cast(MyList)a.dup; The way I see it, an Interface is a generic way of defining a mandatory set of member functions. The problem is that when defining the Interface, one cannot know ahead of time which classes are going to be based on it, and thus you cannot specify the required return type for functions defined in the interface that return an instance of the class being defined. If we could define interfaces thus (or similar syntax) ... interface MutableList { this opSlice(int a, int b); } interface Reproduce { this dup(); } then you can code the class definition as ... class MyList : MutableList, Reproduce { MyList opSlice(int a, int b) { . . . } MyList dup() { . . . } . . . } and the compiler can make the appropriate substitution of 'MyList' for 'this' in the interface definition and still enforce strict type-safety. Then I can do away with the redundant' cast' phrases when using the class, thus making the code more readable and cleaner. And of course, making the Interfaces a lot more generic in that they can be used to build any class definition as required by the class designers. By the way, the use of returning 'Object' in the interfaces still means you need casts plus you lose strict type-safety. -- Derek Melbourne, Australia 31/05/2005 10:04:57 AM -- Derek Melbourne, Australia 31/05/2005 10:34:32 AM
May 30 2005
In article <bjopczpwluat$.z1g5tgrbc43m$.dlg 40tude.net>, Derek Parnell says...My experience with Interfaces is zero, except for dabbling with the D offering. My understanding of what interfaces are is that they are a mechanism for defining a set of methods that must be implemented by a class. About 30 minutes ago I was reading the DSource forum in which 'teqdruid' posted an simple example that shocked me into realizing that there is at least one deficiency in the current Interface syntax.Sounds like you want interfaces to support covariant return types. I wasn't aware that they didn't, so I agree. Sean
May 30 2005
On Tue, 31 May 2005 01:19:16 +0000 (UTC), Sean Kelly wrote:In article <bjopczpwluat$.z1g5tgrbc43m$.dlg 40tude.net>, Derek Parnell says...As I say, I have no real experience with Interfaces, so if 'covariant return types' is the official jargonese for the concept then so be it ;-) I tried to describe the effect in common parlance used within the D language. I just googled the term and got a good description of it from http://c2.com/cgi/wiki?CovariantReturnTypes -- Derek Melbourne, Australia 31/05/2005 11:23:47 AMMy experience with Interfaces is zero, except for dabbling with the D offering. My understanding of what interfaces are is that they are a mechanism for defining a set of methods that must be implemented by a class. About 30 minutes ago I was reading the DSource forum in which 'teqdruid' posted an simple example that shocked me into realizing that there is at least one deficiency in the current Interface syntax.Sounds like you want interfaces to support covariant return types. I wasn't aware that they didn't, so I agree.
May 30 2005
Derek Parnell wrote:This means that the MyList class must implement the interfaces' methods, namely it must define a function called opSlice() that returns a 'MutableList', and function called dup() that must return a 'Reproduce'. However, I would rather have it return a MyList class instead, because as it now stands, to use such a class I must code ...But then doesn't that defeat the purpose of using the interface in the first place? Interfaces should be used when a standard interface is needed. It's a promise to the client that no matter what the underlying implementation, you are guaranteed that these methods will exist and that they will return these types. So imagine this feature you describe is implemented, and I write my code to rely on the fact that the MutableList being returned is actually a MyList. What happens if the underlying implementation changes and returns a SomeoneElsesList instead? I can't cast a MyList to a SomeoneElsesList, so my code is now broken. In general, when programming with interfaces, you should always program *to* the interface. That guarantees that your code will not break if the underlying implementation changes. D's casting mechanism makes it simple enough to handle specific implementations conditionally so that you can do this if you get a MyList, that for SomoneElsesList, and something else for any other MutableList. Allowing an interface implementation to break its interface's contract by varying return types just isn't a good thing, IMO.
May 30 2005
On Tue, 31 May 2005 10:29:17 +0900, Mike Parker wrote:Derek Parnell wrote:I'm new at this so please bear with me.This means that the MyList class must implement the interfaces' methods, namely it must define a function called opSlice() that returns a 'MutableList', and function called dup() that must return a 'Reproduce'. However, I would rather have it return a MyList class instead, because as it now stands, to use such a class I must code ...But then doesn't that defeat the purpose of using the interface in the first place?Interfaces should be used when a standard interface is needed.Yep, that makes sense.It's a promise to the client that no matter what the underlying implementation, you are guaranteed that these methods will exist and that they will return these types.Can I reword this to help me clarify your statement? It's a promise to the code that uses the class, which was defined based on the interface ('the client'), that no matter how the class actually implements the routines named in the interface ('the underlying implementation'), that these routines ('methods') will exist and that they will return the types specified by the interface definition. Yep, that's how I see it too.So imagine this feature you describe is implemented, and I write my code to rely on the fact that the MutableList being returned is actually a MyList. What happens if the underlying implementation changes and returns a SomeoneElsesList instead? I can't cast a MyList to a SomeoneElsesList, so my code is now broken.Are you suggesting a scenario in which the MyList class changes the implementation of its 'opSlice' to return a SomeoneElsesList instead of a MyList class? In my proposed syntax, doing that would cause a compiler error because the Interface would have been defined to say that 'opSlice' must return an instance of the class that is based upon the interface. And as that would be MyList then returning a SomeoneElsesList would be against that Interface's requirements. The problem as I see it is that the current syntax mans that you must 'hard code' the return types in the interface definition. When there are sometimes that you wish it could be defined in terms of a 'symbolic' type rather than a real type. The 'symbolic' type would be resolved at compile time when the class using the interfaces is being defined.In general, when programming with interfaces, you should always program *to* the interface. That guarantees that your code will not break if the underlying implementation changes.Yes, but when a coder is looking at the documentation of a class, let's say a MyList, and sees that opSlice returns something other than the class itself, it is counter-intuitive. It would be like char[] a; char[] b; b = a[1..3]; failing because the slice operation does not return a char[]. Although it may be documented, it is not obvious. "And what is a 'MutableList' anyways?", the coder exclaims ;-)D's casting mechanism makes it simple enough to handle specific implementations conditionally so that you can do this if you get a MyList, that for SomoneElsesList, and something else for any other MutableList.In my view, the cast concept is a way to work around the type-safeness of the language. It is a hack. Unfortunately one which we are forced to use far to often for no good reason.Allowing an interface implementation to break its interface's contract by varying return types just isn't a good thing, IMO.Agreed. But that is not exactly what I'm saying. I'm not saying its okay for a class to return an 'int' when the interface says it should return a 'real'. I am saying, it would be useful to be able to specify an interface in such a way that the return type is resolved at the point in time that the class using the interface is defined, rather than at the time the interface is defined. It is analogous to templates, mixins or the dreaded macro, in that the actual code compiled is deferred. -- Derek Melbourne, Australia 31/05/2005 11:31:55 AM
May 30 2005
If I may add something: An interface is a type of broker between two other parties; nothing more. If both parties respect the contract implied by the broker, then something akin to magic can happen ~ otherwise, all bets are off. As a broker, the Interface must absolve itself from all implementation details. That typically includes concrete types of any kind. Lets call such an animal a "pure" interface. Non-pure interfaces are feasible for many things, but you should really ask if an abstract class is a better approach for such instances. Then there's the "multiple inheritance replacement" thing: it would be convenient to support covariant return types within Interfaces for non-pure usage of this nature, but D does not do this ~ it sticks to the pure implementation instead. You can emulate covariant return types through inherited interface returns instead ~ but it can be a pain, for a number of reasons. Derek Parnell wrote:On Tue, 31 May 2005 10:29:17 +0900, Mike Parker wrote:Derek Parnell wrote:I'm new at this so please bear with me.This means that the MyList class must implement the interfaces' methods, namely it must define a function called opSlice() that returns a 'MutableList', and function called dup() that must return a 'Reproduce'. However, I would rather have it return a MyList class instead, because as it now stands, to use such a class I must code ...But then doesn't that defeat the purpose of using the interface in the first place?Interfaces should be used when a standard interface is needed.Yep, that makes sense.It's a promise to the client that no matter what the underlying implementation, you are guaranteed that these methods will exist and that they will return these types.Can I reword this to help me clarify your statement? It's a promise to the code that uses the class, which was defined based on the interface ('the client'), that no matter how the class actually implements the routines named in the interface ('the underlying implementation'), that these routines ('methods') will exist and that they will return the types specified by the interface definition. Yep, that's how I see it too.So imagine this feature you describe is implemented, and I write my code to rely on the fact that the MutableList being returned is actually a MyList. What happens if the underlying implementation changes and returns a SomeoneElsesList instead? I can't cast a MyList to a SomeoneElsesList, so my code is now broken.Are you suggesting a scenario in which the MyList class changes the implementation of its 'opSlice' to return a SomeoneElsesList instead of a MyList class? In my proposed syntax, doing that would cause a compiler error because the Interface would have been defined to say that 'opSlice' must return an instance of the class that is based upon the interface. And as that would be MyList then returning a SomeoneElsesList would be against that Interface's requirements. The problem as I see it is that the current syntax mans that you must 'hard code' the return types in the interface definition. When there are sometimes that you wish it could be defined in terms of a 'symbolic' type rather than a real type. The 'symbolic' type would be resolved at compile time when the class using the interfaces is being defined.In general, when programming with interfaces, you should always program *to* the interface. That guarantees that your code will not break if the underlying implementation changes.Yes, but when a coder is looking at the documentation of a class, let's say a MyList, and sees that opSlice returns something other than the class itself, it is counter-intuitive. It would be like char[] a; char[] b; b = a[1..3]; failing because the slice operation does not return a char[]. Although it may be documented, it is not obvious. "And what is a 'MutableList' anyways?", the coder exclaims ;-)D's casting mechanism makes it simple enough to handle specific implementations conditionally so that you can do this if you get a MyList, that for SomoneElsesList, and something else for any other MutableList.In my view, the cast concept is a way to work around the type-safeness of the language. It is a hack. Unfortunately one which we are forced to use far to often for no good reason.Allowing an interface implementation to break its interface's contract by varying return types just isn't a good thing, IMO.Agreed. But that is not exactly what I'm saying. I'm not saying its okay for a class to return an 'int' when the interface says it should return a 'real'. I am saying, it would be useful to be able to specify an interface in such a way that the return type is resolved at the point in time that the class using the interface is defined, rather than at the time the interface is defined. It is analogous to templates, mixins or the dreaded macro, in that the actual code compiled is deferred.
May 30 2005
Derek Parnell wrote:On Tue, 31 May 2005 10:29:17 +0900, Mike Parker wrote:Are you suggesting a scenario in which the MyList class changes the implementation of its 'opSlice' to return a SomeoneElsesList instead of a MyList class? In my proposed syntax, doing that would cause a compiler error because the Interface would have been defined to say that 'opSlice' must return an instance of the class that is based upon the interface. And as that would be MyList then returning a SomeoneElsesList would be against that Interface's requirements.And this is what I don't understand. Constidering that MutableList already dictates that opSlice must return a MutableList object, what is the befefit of allowing a MutableList implementation to narrow that scope from MutableList to MyList? The method in question should be able to return any instance of a MutableList implementation, because that's what the interface says it should return. If I'm calling that method from another class, I (generally) don't care if I'm getting what type of MutableList I'm getting.The problem as I see it is that the current syntax mans that you must 'hard code' the return types in the interface definition.That's what an interface is for, isn't it? Call this method, and you will have this type returned.When there are sometimes that you wish it could be defined in termsof > a 'symbolic' type rather than a real type. The 'symbolic' type wouldbe resolved at compile time when the class using the interfaces is being defined.This is the part I'm not getting.Yes, but when a coder is looking at the documentation of a class, let's say a MyList, and sees that opSlice returns something other than the class itself, it is counter-intuitive. It would be likechar[] a; char[] b;b = a[1..3]; failing because the slice operation does not return a char[].Although > it may be documented, it is not obvious. "And what is a 'MutableList'anyways?", the coder exclaims ;-)Okay, this is why opSlice is a bad example. Operator overloads are already part of the language spec, and have no business being part of an interface definition in the first place (unless you want to enforce a specific behavior for special cases). interface Foo { void amethod(); } class Bar : Foo { void amethod() {} } class BarToo : Foo { void amethod() {} } interface Baz { Foo getFoo(); } class BazImpl : Baz { Foo getFoo(); } Baz says that everytime I call Foo, I will get a Foo. Maybe I'll get a Bar or a BarToo, but it will always be a Foo. They syntax you propose would allow this: class BazImplToo : Baz { Bar getFoo() {} } This means that BazImplToo no longer strictly adheres to the Baz interface, because it can't return any type of Foo, but only Foos which are instances of, or extended instances of, Bar. This is how I'm looking at it. What I'm no getting is what benefit this brings.
May 30 2005
On Tue, 31 May 2005 12:50:51 +0900, Mike Parker wrote:Derek Parnell wrote:Stop there! What I'm proposing is that MutableList dictates that opSlice must return an instance of *whatever* class that is using MutableList as one of its building blocks. For instance: interface ML { this meth_one(int a, int b); } class BaseList { . . . } class ListOne: BaseList, ML { ListOne meth_one(int a, int b) { ListOne x = new ListOne; . . . return x; } } class ListTwo: ML { ListTwo meth_one(int a, int b) { ListTwo x = new ListTwo; . . . return x; } } By using the syntax "this funcname()" inside the interface definition, I'm trying to tell the compiler that the return type is not known yet and will only be known when this interface is used on a class definition, at which time the compiler will substitute the word 'this' with the name of the class being defined. The contract ('interface promise') is still being met. The only thing is that the specific return type is not known at the time the interface was designed. It allows much more generic interfaces to be designed. It says, "when using this interface to define a class, you must implement a member function that accepts these parameters are returns an instance of the class that you are defining."On Tue, 31 May 2005 10:29:17 +0900, Mike Parker wrote:Are you suggesting a scenario in which the MyList class changes the implementation of its 'opSlice' to return a SomeoneElsesList instead of a MyList class? In my proposed syntax, doing that would cause a compiler error because the Interface would have been defined to say that 'opSlice' must return an instance of the class that is based upon the interface. And as that would be MyList then returning a SomeoneElsesList would be against that Interface's requirements.And this is what I don't understand. Constidering that MutableList already dictates that opSlice must return a MutableList object,what is the befefit of allowing a MutableList implementation to narrow that scope from MutableList to MyList?Narrow? How is it narrowing it? I would have thought I was expanding it. Are you thinking that I mean that when the class is being defined, that the interface is then 'locked' into RAM or such.The method in question should be able to return any instance of a MutableList implementation, because that's what the interface says it should return.Currently, yes. But what-if you could tell the compile to be more flexible.If I'm calling that method from another class, I (generally) don't care if I'm getting what type of MutableList I'm getting.Huh? There is only one type of MutableList. Are you saying that any class that uses MutableList as a basis becomes a type of MutableList? How does that work with multiple interfaces being used on a single class definition?> The problem as I see it is that the current syntax mans that you must > 'hard code' the return types in the interface definition. That's what an interface is for, isn't it? Call this method, and you will have this type returned.Yes.> When there are sometimes that you wish it could be defined in terms of > a 'symbolic' type rather than a real type. The 'symbolic' type would > be resolved at compile time when the class using the interfaces is > being defined. This is the part I'm not getting.Hopefully I've described more fully now.> Yes, but when a coder is looking at the documentation of a class, > let's say > a MyList, and sees that opSlice returns something other than the class > itself, it is counter-intuitive. It would be like > char[] a; > char[] b; > b = a[1..3]; > > failing because the slice operation does not return a char[]. Although > it may be documented, it is not obvious. "And what is a 'MutableList' > anyways?", the coder exclaims ;-) Okay, this is why opSlice is a bad example. Operator overloads are already part of the language spec, and have no business being part of an interface definition in the first place (unless you want to enforce a specific behavior for special cases). interface Foo { void amethod(); } class Bar : Foo { void amethod() {} } class BarToo : Foo { void amethod() {} } interface Baz { Foo getFoo(); } class BazImpl : Baz { Foo getFoo(); } Baz says that everytime I call Foo, I will get a Foo. Maybe I'll get a Bar or a BarToo, but it will always be a Foo.This is the part that I'm not getting. Given that an interface is a list of methods that must be implemented, how can a function return an interface? Are you saying that the getFoo() function is returning a list of method signatures? Why would I want that? It seems that you are suggesting that an interfaces is really some sort of light-weight class. If the classes Bar and BarToo also implemented other methods and data,, but different from each other, what would getFoo() return? Is it just an object that allows you to call only the Foo methods implemented in both Bar and BarToo, but not access the other methods or data in them?They syntax you propose would allow this: class BazImplToo : Baz { Bar getFoo() {} }No, it will not. Because Baz says it must return a Foo, returning a Bar is wrong. And even if Baz said it can return a 'this thingy', your example would still be wrong because a Bar is not a BazImplToo.This means that BazImplToo no longer strictly adheres to the Baz interface, because it can't return any type of Foo, but only Foos which are instances of, or extended instances of, Bar. This is how I'm looking at it. What I'm no getting is what benefit this brings.I'll try another example: interface Foo { this amethod(); } interface Baz { this bmethod(); int cmethod(); } class Bar : Foo { Bar amethod() { . . .} private real x; } class BarToo : Foo, Baz { BarToo amethod() { . . .} BarToo bmethod() { . . .} int cmethod(){ . . . } } class BazImpl : Baz { BarImpl bmethod() { . . .} int cmethod(){ . . . } } -- Derek Melbourne, Australia 31/05/2005 1:55:36 PM
May 30 2005
Derek Parnell wrote: <snip>Part of the power within Interfaces comes from their agnostic properties: if there is no concrete implementation referenced anywhere within, then /anybody/ can implement the interface and magically be compatible will all clients of said interface. That is; If IMutableList is an interface, each of you, John, and I can provide a completely independent implementation, yet all clients of IMutableList just don't care which one is "plugged in" at any given time. There are times when the client will want to know, but that's perhaps a different issue. You'll often find such things returned via the so-called Factory Pattern. This is why interfaces typically reference only other Interfaces (in return values and/or arguments), or define enums and other simple attributes. They were intended to be a pure abstraction of a contract. That doesn't mean some interesting mutations can't be proposed, but I think it's where some confusion can arise.If I'm calling that method from another class, I (generally) don't care if I'm getting what type of MutableList I'm getting.Huh? There is only one type of MutableList. Are you saying that any class that uses MutableList as a basis becomes a type of MutableList? How does that work with multiple interfaces being used on a single class definition?The traditional Interface would return another interface instead.The problem as I see it is that the current syntax mans that you must 'hard code' the return types in the interface definition.That's what an interface is for, isn't it? Call this method, and you will have this type returned.
May 30 2005
On Mon, 30 May 2005 21:55:16 -0700, kris wrote:Derek Parnell wrote: <snip>As I say, I *really* am new to all of this Interface stuff. The stuff you wrote below may as well been written in (digital?) Martian for the amount of it I know I really understood ;-)If I'm calling that method from another class, I (generally) don't care if I'm getting what type of MutableList I'm getting.Huh? There is only one type of MutableList. Are you saying that any class that uses MutableList as a basis becomes a type of MutableList? How does that work with multiple interfaces being used on a single class definition?Part of the power within Interfaces comes from their agnostic properties:'agnostic properties' = defines signatures (name, and return and input parameters) and doesn't care who or how they are implemented?if there is no concrete implementation'concrete implementation' = implementation code that is compilable?referenced anywhere within,Is this saying "if the code that defines an interface does not, itself, reference any actual implementation code"? What do you mean by 'reference'? Do you mean 'contains'? Or what???then /anybody/ can implement the interface and magically be compatible will all clients of said interface. That is; If IMutableList is an interface, each of you, John, and I can provide a completely independent implementation, yet all clients of IMutableList just don't care which one is "plugged in" at any given time.Is a "client of IMutableList" any class that inherits IMutable? And does this mean that given the code below ... interface iOne { double amethod(); } class Circle: iOne { double amethod() { return (radius * 2 * PI) / 360.00L ; } real bmethod() { ... } } class BattleTank: iOne { double amethod() { return RemainingAmmo / FireRate; } byte[] cmethod() { ... } } class HumanHeart: iOne { double amethod() { return Ventricle.Capacity + Atrium.Capacity; } long* dmethod() { ... } } that somehow the classes Circle, BattleTank and HumanHeart are related in so far as I can use them interchangeably at times? And what do you mean by "plugged in". Is this a runtime or a compile time operation?There are times when the client will want to know, but that's perhaps a different issue.Has the meaning of "client" changed here? A what is it that the client might want to know?You'll often find such things returned via the so-called Factory Pattern.What things? Interfaces? Class instances?This is why interfaces typically reference only other Interfaces (in return values and/or arguments), or define enums and other simple attributes.Are you saying that the methods defined in an interface definition typically only name other interfaces as data types in the return value and function arguments? Then can they specify functions that can be comnpiled? Surely, somewhere along the way a method in an interface must use real data types?They were intended to be a pure abstraction of a contract.Yes, this is my understanding of them too. Nothing concrete. *JUST* a list of function signatures that is used by the compiler to ensure that classes that use the interface have all the interface's methods implemented. My assumption is that there is never any object code that is generated by an interface definition - it is just a device used by the compiler and not the linker.That doesn't mean some interesting mutations can't be proposed, but I think it's where some confusion can arise.Not really. I'm overly confused as it is ;-)What is meant (i.e. Show me the code) by an interface *returning* another interface? How can something that is never instantiated execute any code to return anything? Or does this terminology ('return another interface') refer to some action by the compiler and not a run time action? -- Derek Melbourne, Australia 31/05/2005 2:57:28 PMThe traditional Interface would return another interface instead.The problem as I see it is that the current syntax mans that you must 'hard code' the return types in the interface definition.That's what an interface is for, isn't it? Call this method, and you will have this type returned.
May 30 2005
Derek Parnell wrote:As I say, I *really* am new to all of this Interface stuff. The stuff you wrote below may as well been written in (digital?) Martian for the amount of it I know I really understood ;-)Funny!Right. If I understand you correctly :)Part of the power within Interfaces comes from their agnostic properties:'agnostic properties' = defines signatures (name, and return and input parameters) and doesn't care who or how they are implemented?Yeah; the actual implementation of an Interface is closely related to the implementation of abstract methods defined in a superclass ~ both are 'concrete' rather than 'abstract'. It is only said implementation that produces linkable code.if there is no concrete implementation'concrete implementation' = implementation code that is compilable?Aye: "if the /declaration/ of an Interface does not ..." ~ there's no code in an Interface itself. By reference, I mean the Interface module does not import any module declaring a 'concrete', linkable, anything. It may very well import other Interfaces. Repeat ad nauseum <g>referenced anywhere within,Is this saying "if the code that defines an interface does not, itself, reference any actual implementation code"? What do you mean by 'reference'? Do you mean 'contains'? Or what???No. Or not really. The client of an Interface is usually a consumer/user of it, like someone buying something in a store. A class providing a concrete, linkable version of some Interface is said to "implement" the interface. If Walter were to define/declare an Interface describing a String class (*cough*), and you were to write an implementing class then I, as a consumer/user, could instantiate the interface via your concrete implementation. Further, John could write an alternate concrete implementation, and I could use that instead, without changing my 'client' code. That is, If I stick to using the Interface only, then I can switch between one or the other. For such simple usage, one could use an abstract base class instead. Since you mentioned the use of inheritance, it's worth noting that each Interface can inherit from others; multiple others if appropriate.then /anybody/ can implement the interface and magically be compatible will all clients of said interface. That is; If IMutableList is an interface, each of you, John, and I can provide a completely independent implementation, yet all clients of IMutableList just don't care which one is "plugged in" at any given time.Is a "client of IMutableList" any class that inherits IMutable?And does this mean that given the code below ... interface iOne { double amethod(); } class Circle: iOne { double amethod() { return (radius * 2 * PI) / 360.00L ; } real bmethod() { ... } } class BattleTank: iOne { double amethod() { return RemainingAmmo / FireRate; } byte[] cmethod() { ... } } class HumanHeart: iOne { double amethod() { return Ventricle.Capacity + Atrium.Capacity; } long* dmethod() { ... } } that somehow the classes Circle, BattleTank and HumanHeart are related in so far as I can use them interchangeably at times?Yes. The Interface is just a contract ~ if various implementations attach completely different semantics to that Interface, that's a problem <g>. Oftentimes, an Interface is used as a means to discuss details of how two parties will collaborate ~ the mechanics are enforced by the Interface methods, but the semantics are agreed upon in other ways; usually heavily documented in the Interface module. An important point (I think) is this: an Interface is a means of /decoupling/ two independent entities, such that they no longer contain explicit ties to one another. Again, one can use an abstract base class for simple cases ~ Interfaces provide the extra 'decoupling' horsepower when needed, within a singly-rooted hierarchy.And what do you mean by "plugged in". Is this a runtime or a compile time operation?It can be both ~ largely depends upon language capabilities. One key aspect of 'pluggable' systems is that a client should not know anything more than what the contract exposes. In other words, anything that /changes/ across different implementations should be abstracted via the Interface. The same is true for an abstract base-class. This is part and parcel of the decoupling aspect.Some clients break the contract when they want to use specific capabilities of certain concrete implementations. They do this by casting the Interface to a known, concrete implementation, and using that instead. This is bogus, but it does happen. All decooupling efforts are thus borked. The resolution is to refactor the interface, or lay down some smack upon the client.There are times when the client will want to know, but that's perhaps a different issue.Has the meaning of "client" changed here? A what is it that the client might want to know?Factories return concrete class instances; but typically do so by returning an Interface. Specifically, a class instance that implements the appropriate interface: The factory is usually consider a producer in such cases; it hides how the Interface is implemented by encapsulating the concrete instance within itself. The client/consumer doesn't know, or care, from whence the implementation cometh from.You'll often find such things returned via the so-called Factory Pattern.What things? Interfaces? Class instances?Usually, yes. This makes them agnostic of any particular implementation. It's not a hard requirement, but it's necessary where "fully decoupled" is desirable.This is why interfaces typically reference only other Interfaces (in return values and/or arguments), or define enums and other simple attributes.Are you saying that the methods defined in an interface definition typically only name other interfaces as data types in the return value and function arguments?Then can they specify functions that can be comnpiled? Surely, somewhere along the way a method in an interface must usereal > datatypes?Traditional Interfaces are contract declarations only. No code is specified within them. That occurs within Concrete implementations of the Interface.Aye. In D, I believe they are just like a list of delegate pointers.They were intended to be a pure abstraction of a contract.Yes, this is my understanding of them too. Nothing concrete. *JUST* a list of function signatures that is used by the compiler to ensure that classes that use the interface have all the interface's methods implemented. My assumption is that there is never any object code that is generated by an interface definition - it is just a device used by the compiler and not the linker.Note the declaration of IVehicle. It is independent of any concrete Transmission. As would be any client of IVehicle. Though I'm not sure what I'd do with a concrete transmission; or a concrete bus, for that matter :) BTW; these examples are somewhat trivialized, and don't even touch upon multiple Interface implementations or Interface inheritance. I'm sure you realize that.That doesn't mean some interesting mutations can't be proposed, but I think it's where some confusion can arise.Not really. I'm overly confused as it is ;-)What is meant (i.e. Show me the code) by an interface *returning* another interface? How can something that is never instantiated execute any code to return anything? Or does this terminology ('return another interface') refer to some action by the compiler and not a run time action?The traditional Interface would return another interface instead.The problem as I see it is that the current syntax mans that you must 'hard code' the return types in the interface definition.That's what an interface is for, isn't it? Call this method, and you will have this type returned.
May 31 2005
On Tue, 31 May 2005 00:51:21 -0700, kris wrote: [a whole lot of good things about Interfaces that I'm still digesting.] Things are clearer now but I still need to get my head around this better. More research is required... -- Derek Parnell Melbourne, Australia 1/06/2005 2:03:31 AM
May 31 2005
"kris" <fu bar.org> wrote in message news:d7h4lh$12nu$1 digitaldaemon.com...listYes, this is my understanding of them too. Nothing concrete. *JUST* aclassesof function signatures that is used by the compiler to ensure thatanthat use the interface have all the interface's methods implemented. My assumption is that there is never any object code that is generated bytheinterface definition - it is just a device used by the compiler and notNo, in D, an interface is a pointer to a vtbl[]. Each interface implemented by a class gets a vptr allocated in the class instance, and that vptr points to a vtbl[] for the functions that implement it. Casting a class to an interface means adding an offset to the 'this' pointer to point to the vptr member for that interface. Casting from an interface back to the class means subtracting that offset. The subtract is a little tricky since the pointer doesn't know where it came from, so the first entry in the interface's vtbl[] is an instance of the class Interface with the necessary offset. The cast is handled by the library function _d_interface_cast(). So, an interface "instantiation" is a physical pointer that can get copied, passed as a function argument, etc. The problem with interface covariance with classes is that that pointer is not the same as the 'this' pointer to a class. There are ways to deal with this, such as putting out special vtbl[]s with 'this' adjustor thunks in them, but D doesn't do that now and since it's a complex implementation problem, it won't for now. Covariance for class inheritance works because the 'this' for the base class is exactly the same as the 'this' for a derived class.linker.Aye. In D, I believe they are just like a list of delegate pointers.
May 31 2005
In article <d7j9s9$fq8$1 digitaldaemon.com>, Walter says...The problem with interface covariance with classes is that that pointer is not the same as the 'this' pointer to a class. There are ways to deal with this, such as putting out special vtbl[]s with 'this' adjustor thunks in them, but D doesn't do that now and since it's a complex implementation problem, it won't for now.Sounds reasonable. I kind of see interface implementation as a contract anyway, so I'd accept the argument that return type is part of that contract. Sean
May 31 2005
in D, an interface is a pointer to a vtbl[]. Each interface implemented by a class gets a vptr allocated in the class instance, and that vptr points to a vtbl[] for the functions that implement it.Such a vtbl[] coud be created at runtime as well, right? So perhaps there could be a new language-construct (I call it protocoll for now) which basically behaes like an interface, but doesn't need to be explicitly implemented: protocol Foo { void method (); } class Bar { void method () {...} } void function (Foo foo) {...} void main () { function (new Bar()); // OK } Protocolls might be a bit more expensive than interfaces as the vtbl[] has to be generated at runtime, but they are more flexible as well. E.g. you can write a protocol that has a subset of some classes you haven't written and this way allow to use these classes polymorphically in your own framework.
Jun 01 2005
In article <d7k1b0$15md$1 digitaldaemon.com>, Matthias Becker says...Cool idea, but this scares me a bit--it allows an object to impersonate something it was never intended to impersonate. What if Bar.method has a function that has nothing to do with what Foo.method is supposed to do? Seanin D, an interface is a pointer to a vtbl[]. Each interface implemented by a class gets a vptr allocated in the class instance, and that vptr points to a vtbl[] for the functions that implement it.Such a vtbl[] coud be created at runtime as well, right? So perhaps there could be a new language-construct (I call it protocoll for now) which basically behaes like an interface, but doesn't need to be explicitly implemented: protocol Foo { void method (); } class Bar { void method () {...} } void function (Foo foo) {...} void main () { function (new Bar()); // OK } Protocolls might be a bit more expensive than interfaces as the vtbl[] has to be generated at runtime, but they are more flexible as well. E.g. you can write a protocol that has a subset of some classes you haven't written and this way allow to use these classes polymorphically in your own framework.
Jun 01 2005
I guess you'll find this idea is close to yours: http://www.heron-language.com/interfaces.html Chapter 'Unintrusive Retroactive Polymorphism' The idea is just perfect, imho. Andrew. "Matthias Becker" <Matthias_member pathlink.com> wrote in message news:d7k1b0$15md$1 digitaldaemon.com...in D, an interface is a pointer to a vtbl[]. Each interface implemented by a class gets a vptr allocated in the class instance, and that vptr points to a vtbl[] for the functions that implement it.Such a vtbl[] coud be created at runtime as well, right? So perhaps there could be a new language-construct (I call it protocoll for now) which basically behaes like an interface, but doesn't need to be explicitly implemented: protocol Foo { void method (); } class Bar { void method () {...} } void function (Foo foo) {...} void main () { function (new Bar()); // OK } Protocolls might be a bit more expensive than interfaces as the vtbl[] has to be generated at runtime, but they are more flexible as well. E.g. you can write a protocol that has a subset of some classes you haven't written and this way allow to use these classes polymorphically in your own framework.
Jun 04 2005
In article <d7t04k$5se$1 digitaldaemon.com>, Andrew Fedoniouk says...I guess you'll find this idea is close to yours: http://www.heron-language.com/interfaces.html Chapter 'Unintrusive Retroactive Polymorphism' The idea is just perfect, imho. Andrew.I don't know much about Objective-C but I think it also has a concept roughly like that called "informal protocols" (a protocol in Objective-C is like an interface in D). It would be an interesting thought experiment to take the object model of Objective-C and graft it onto the non-object-model of D and presto Objective-D. Scary but fun to think about. :-)"Matthias Becker" <Matthias_member pathlink.com> wrote in message news:d7k1b0$15md$1 digitaldaemon.com...in D, an interface is a pointer to a vtbl[]. Each interface implemented by a class gets a vptr allocated in the class instance, and that vptr points to a vtbl[] for the functions that implement it.Such a vtbl[] coud be created at runtime as well, right? So perhaps there could be a new language-construct (I call it protocoll for now) which basically behaes like an interface, but doesn't need to be explicitly implemented: protocol Foo { void method (); } class Bar { void method () {...} } void function (Foo foo) {...} void main () { function (new Bar()); // OK } Protocolls might be a bit more expensive than interfaces as the vtbl[] has to be generated at runtime, but they are more flexible as well. E.g. you can write a protocol that has a subset of some classes you haven't written and this way allow to use these classes polymorphically in your own framework.
Jun 04 2005
Christopher Diggins was around here for a little while: http://www.digitalmars.com/d/archives/digitalmars/D/1097.html I thought it was a good idea also. "Andrew Fedoniouk" <news terrainformatica.com> wrote in message news:d7t04k$5se$1 digitaldaemon.com...I guess you'll find this idea is close to yours: http://www.heron-language.com/interfaces.html Chapter 'Unintrusive Retroactive Polymorphism' The idea is just perfect, imho. Andrew. "Matthias Becker" <Matthias_member pathlink.com> wrote in message news:d7k1b0$15md$1 digitaldaemon.com...therein D, an interface is a pointer to a vtbl[]. Each interface implemented by a class gets a vptr allocated in the class instance, and that vptr points to a vtbl[] for the functions that implement it.Such a vtbl[] coud be created at runtime as well, right? So perhapsbasicallycould be a new language-construct (I call it protocoll for now) whichhasbehaes like an interface, but doesn't need to be explicitly implemented: protocol Foo { void method (); } class Bar { void method () {...} } void function (Foo foo) {...} void main () { function (new Bar()); // OK } Protocolls might be a bit more expensive than interfaces as the vtbl[]to be generated at runtime, but they are more flexible as well. E.g. you can write a protocol that has a subset of some classes you haven't written and this way allow to use these classes polymorphically in your own framework.
Jun 04 2005
"Derek Parnell" <derek psych.ward> wrote in message news:bjopczpwluat$.z1g5tgrbc43m$.dlg 40tude.net...My experience with Interfaces is zero, except for dabbling with the D offering. My understanding of what interfaces are is that they are a mechanism for defining a set of methods that must be implemented by a class. About 30 minutes ago I was reading the DSource forum in which 'teqdruid' posted an simple example that shocked me into realizing that there is at least one deficiency in the current Interface syntax.That's very weird. I always assumed D's interfaces supported covariant return types, as inherited classes do, though I've not yet needed to use them, so I never knew it didn't work. Maybe it's just an oversight in the spec?
May 30 2005
"Derek Parnell" <derek psych.ward> wrote in message news:bjopczpwluat$.z1g5tgrbc43m$.dlg 40tude.net...If we could define interfaces thus (or similar syntax) ... interface MutableList { this opSlice(int a, int b); } interface Reproduce { this dup(); } then you can code the class definition as ... class MyList : MutableList, Reproduce { MyList opSlice(int a, int b) { . . . } MyList dup() { . . . } . . . }I can't help but think that an interface template will fit the bill here: interface MutableList(T) { T opSlice(int a, int b); } interface Reproduce(T) { T dup(); } class MyList : MutableList!(MyList), Reproduce!(MyList) { MyList opSlice(int a, int b) { . . . } MyList dup() { . . . } . . . }
May 31 2005
On Tue, 31 May 2005 20:07:32 -0700, Walter wrote:"Derek Parnell" <derek psych.ward> wrote in message news:bjopczpwluat$.z1g5tgrbc43m$.dlg 40tude.net...I didn't know one could do that! I think I'll update the wiki DocComments about this. This is exactly what is required for my purposes (though the syntax is a tad bulky). -- Derek Melbourne, Australia 1/06/2005 1:16:59 PMIf we could define interfaces thus (or similar syntax) ... interface MutableList { this opSlice(int a, int b); } interface Reproduce { this dup(); } then you can code the class definition as ... class MyList : MutableList, Reproduce { MyList opSlice(int a, int b) { . . . } MyList dup() { . . . } . . . }I can't help but think that an interface template will fit the bill here:
May 31 2005