digitalmars.D - typeid() broken for interfaces?
- Gor Gyolchanyan (10/10) Nov 30 2012 interface I { }
- Maxim Fomin (4/12) Nov 30 2012 It works according to spec. Object is expression of type
- Gor Gyolchanyan (6/19) Nov 30 2012 So the interfaces aren't supposed to hold a TypeInfo? That doesn't sound
- Maxim Fomin (7/11) Nov 30 2012 You can find information about interfaces and classes at
- Walter Bright (3/10) Dec 01 2012 That works, because classes are classes. Classes are not interfaces.
- Gor Gyolchanyan (5/19) Dec 02 2012 --
- pjmlp (2/27) Dec 02 2012 Because interfaces don't extend object?
- Walter Bright (3/4) Dec 02 2012 Think of it this way. An int can be implicitly converted to a long, but
- Gor Gyolchanyan (9/14) Dec 02 2012 Wouldn't it be better to return the class's typeinfo if it is a class an...
- Walter Bright (4/9) Dec 02 2012 A particular interface can be implemented by many different class types,...
- Gor Gyolchanyan (14/24) Dec 03 2012 Currently typeid(typeid(Interface)) == typeid(ClassInfo). So the interfa...
- Maxim Fomin (14/15) Dec 03 2012 Are you sure?
- Walter Bright (4/5) Dec 03 2012 I'm curious what you expect typeid(typeid(something)) to do. I would
- deadalnix (3/18) Dec 02 2012 I'm still waiting to see an object that implement an interface
- Jonathan M Davis (5/7) Dec 02 2012 Isn't that the case with the COM stuff? I remember there being something...
- Walter Bright (2/4) Dec 02 2012 COM objects that come from code not written in D.
- deadalnix (2/7) Dec 02 2012 OK that make sense. I have to think about it.
- Paulo Pinto (9/19) Dec 03 2012 When coding against interfaces, it is always a good decision not
- Jacob Carlborg (12/18) Dec 03 2012 Well, one would might think that this would work:
- Maxim Fomin (11/32) Dec 03 2012 Object does not implement interface I, so why should interface
- Jacob Carlborg (6/10) Dec 03 2012 Because Object is the root of the class hierarchy. That's how it works
- Jacob Carlborg (5/8) Dec 03 2012 Note, I'm not saying that an interface should be implicitly converted to...
- Walter Bright (2/4) Dec 03 2012 But not all interfaces come from Objects.
- deadalnix (10/15) Dec 03 2012 So I thought about all that.
- Walter Bright (9/25) Dec 03 2012 I really don't know what issue you're trying to solve here. The typeid's...
- deadalnix (8/17) Dec 03 2012 You can't instantiate interface. So an underlying type MUST
- Maxim Fomin (20/30) Dec 03 2012 You cannot create interface instance with new operator because
- Paulo Pinto (11/43) Dec 04 2012 Given my experience with the interface concept in several OO
- foobar (6/38) Dec 04 2012 The above is a perfectly safe conversion.
- Jacob Carlborg (4/5) Dec 03 2012 No, but those are statically known.
- foobar (12/17) Dec 04 2012 IMO this is a design mistake - the special case is preferred over
- Jacob Carlborg (4/15) Dec 04 2012 Exactly, I couldn't agree more.
- Maxim Fomin (34/42) Dec 04 2012 And what happens if nobody implements an interface?
- deadalnix (5/18) Dec 04 2012 The same as abstract classes : you can get the typeid by looking
- Jacob Carlborg (19/39) Dec 04 2012 You cannot really get an instance of an interface without having a class...
- Paulo Pinto (7/53) Dec 04 2012 If you want to call toSring, it should be part of the interface
- foobar (15/79) Dec 04 2012 Generally speaking you are right. But specifically regarding
- Paulo Pinto (11/93) Dec 04 2012 For languages without generics where you need a common base class
- foobar (16/42) Dec 04 2012 That's a lot of duplication considering D already provides this
- Jonathan M Davis (6/8) Dec 04 2012 Though per the last major discussion on const-correctness and Object, it...
- foobar (9/20) Dec 05 2012 In other words, the plan is to pretty much deprecate Object? I
- Jonathan M Davis (24/48) Dec 05 2012 No. The plan is not to deprecate Object. The reality is that those funct...
- foobar (6/78) Dec 06 2012 But these are the methods of Object. So even if Object itself
- Jonathan M Davis (9/13) Dec 06 2012 It's would still be perfectly possible to pass around Object if you want...
- deadalnix (3/7) Dec 06 2012 I don't see any major drawback in keeping Object. What are the
- foobar (9/20) Dec 05 2012 In other words, the plan is to pretty much deprecate Object? I
- foobar (9/20) Dec 05 2012 In other words, the plan is to pretty much deprecate Object? I
interface I { } class C: I { } I object = new C; assert(typeid(object) == typeid(C)); // fails Is this normal or is it a bug? Note, that the same works fine in case of a base class, rather then an interface. -- Bye, Gor Gyolchanyan.
Nov 30 2012
On Friday, 30 November 2012 at 10:05:21 UTC, Gor Gyolchanyan wrote:interface I { } class C: I { } I object = new C; assert(typeid(object) == typeid(C)); // fails Is this normal or is it a bug? Note, that the same works fine in case of a base class, rather then an interface.It works according to spec. Object is expression of type interface I, so no dynamic type search is performed.
Nov 30 2012
So the interfaces aren't supposed to hold a TypeInfo? That doesn't sound right. That makes interfaces useless in a very large set of use cases. On Fri, Nov 30, 2012 at 2:55 PM, Maxim Fomin <maxim maxim-fomin.ru> wrote:On Friday, 30 November 2012 at 10:05:21 UTC, Gor Gyolchanyan wrote:-- Bye, Gor Gyolchanyan.interface I { } class C: I { } I object = new C; assert(typeid(object) == typeid(C)); // fails Is this normal or is it a bug? Note, that the same works fine in case of a base class, rather then an interface.It works according to spec. Object is expression of type interface I, so no dynamic type search is performed.
Nov 30 2012
On Friday, 30 November 2012 at 11:04:10 UTC, Gor Gyolchanyan wrote:So the interfaces aren't supposed to hold a TypeInfo? That doesn't sound right. That makes interfaces useless in a very large set of use cases.You can find information about interfaces and classes at http://dlang.org/abi.html (interfaces have a pointer to vtbl[] which entries have pointers to TypeInfo). You can also write enhancement request if you consider your proposal worth implementing (but I don't understand what exactly you want).
Nov 30 2012
On 11/30/2012 9:04 PM, Gor Gyolchanyan wrote:interface I { } class C: I { } I object = new C; assert(typeid(object) == typeid(C)); // fails Is this normal or is it a bug?Normal, since the typeids of interfaces are not the same as for classes.Note, that the same works fine in case of a base class, rather then an interface.That works, because classes are classes. Classes are not interfaces.
Dec 01 2012
What's the logic in this behavior? On Sun, Dec 2, 2012 at 1:28 AM, Walter Bright <newshound2 digitalmars.com>wrote:On 11/30/2012 9:04 PM, Gor Gyolchanyan wrote:-- Bye, Gor Gyolchanyan.interface I { } class C: I { } I object = new C; assert(typeid(object) == typeid(C)); // fails Is this normal or is it a bug?Normal, since the typeids of interfaces are not the same as for classes. Note, that the same works fine in case of a base class, rather then aninterface.That works, because classes are classes. Classes are not interfaces.
Dec 02 2012
On Sunday, 2 December 2012 at 19:26:47 UTC, Gor Gyolchanyan wrote:What's the logic in this behavior? On Sun, Dec 2, 2012 at 1:28 AM, Walter Bright <newshound2 digitalmars.com>wrote:Because interfaces don't extend object?On 11/30/2012 9:04 PM, Gor Gyolchanyan wrote:interface I { } class C: I { } I object = new C; assert(typeid(object) == typeid(C)); // fails Is this normal or is it a bug?Normal, since the typeids of interfaces are not the same as for classes. Note, that the same works fine in case of a base class, rather then aninterface.That works, because classes are classes. Classes are not interfaces.
Dec 02 2012
On 12/3/2012 6:26 AM, Gor Gyolchanyan wrote:What's the logic in this behavior?Think of it this way. An int can be implicitly converted to a long, but they have different typeid's because they are different bits.
Dec 02 2012
Wouldn't it be better to return the class's typeinfo if it is a class and the interface's typeinfo if it isn't? The interface would then return the most derived typeinfo that it knows of. I think, just because the interface can be something other then a class object, doesn't mean it should be treated as though it will never be a class object. On Mon, Dec 3, 2012 at 5:10 AM, Walter Bright <newshound2 digitalmars.com>wrote:On 12/3/2012 6:26 AM, Gor Gyolchanyan wrote:-- Bye, Gor Gyolchanyan.What's the logic in this behavior?Think of it this way. An int can be implicitly converted to a long, but they have different typeid's because they are different bits.
Dec 02 2012
On 12/3/2012 4:43 PM, Gor Gyolchanyan wrote:Wouldn't it be better to return the class's typeinfo if it is a class and the interface's typeinfo if it isn't? The interface would then return the most derived typeinfo that it knows of. I think, just because the interface can be something other then a class object, doesn't mean it should be treated as though it will never be a class object.A particular interface can be implemented by many different class types, or by something that isn't even a class, so returning a typeid that's a class typeid would make it impossible to compare one with another.
Dec 02 2012
Currently typeid(typeid(Interface)) == typeid(ClassInfo). So the interfaces are using a class's type info, which doesn't make much sense considering the aforementioned interface logic. If interfaces get their own type info (like one without a "base" member), it might have an a member called "objectType", which would be of type ClassInfo and would be null if the interface is not a class object. then the interface would be perfectly comparable with other interface types and in case it happens to be a class object, that could be tested too. And with some more info, the offset of the interface could be retrieved to compute the object's this reference (all in case it is indeed a class object). On Mon, Dec 3, 2012 at 9:58 AM, Walter Bright <newshound2 digitalmars.com>wrote:On 12/3/2012 4:43 PM, Gor Gyolchanyan wrote:-- Bye, Gor Gyolchanyan.Wouldn't it be better to return the class's typeinfo if it is a class and the interface's typeinfo if it isn't? The interface would then return the most derived typeinfo that it knows of. I think, just because the interface can be something other then a class object, doesn't mean it should be treated as though it will never be a class object.A particular interface can be implemented by many different class types, or by something that isn't even a class, so returning a typeid that's a class typeid would make it impossible to compare one with another.
Dec 03 2012
On Monday, 3 December 2012 at 10:49:54 UTC, Gor Gyolchanyan wrote:Currently typeid(typeid(Interface)) == typeid(ClassInfo). SoAre you sure? //dpaste seems to be down import std.stdio; interface I { } class C: I { } void main() { I object = new C; writeln( typeid(object) == typeid(C) ); writeln( typeid(Interface) == typeid(ClassInfo) ); writeln( typeid(typeid(Interface)) == typeid(ClassInfo) ); } Using latest dmd from git head I get three falses.
Dec 03 2012
On 12/3/2012 9:47 PM, Gor Gyolchanyan wrote:Currently typeid(typeid(Interface)) == typeid(ClassInfo).I'm curious what you expect typeid(typeid(something)) to do. I would expect it to return the typeid of whatever object typeid returns. That has nothing to do with what 'something' is.
Dec 03 2012
On Saturday, 1 December 2012 at 21:28:05 UTC, Walter Bright wrote:On 11/30/2012 9:04 PM, Gor Gyolchanyan wrote:I'm still waiting to see an object that implement an interface but that isn't a class instance.interface I { } class C: I { } I object = new C; assert(typeid(object) == typeid(C)); // fails Is this normal or is it a bug?Normal, since the typeids of interfaces are not the same as for classes.Note, that the same works fine in case of a base class, rather then an interface.That works, because classes are classes. Classes are not interfaces.
Dec 02 2012
On Sunday, December 02, 2012 23:17:33 deadalnix wrote:I'm still waiting to see an object that implement an interface but that isn't a class instance.Isn't that the case with the COM stuff? I remember there being something weird about them being interfaces but not classes, which is part of what has screwed over some of the interface-related stuff like opEquals. - Jonathan M Davis
Dec 02 2012
On 12/3/2012 9:17 AM, deadalnix wrote:I'm still waiting to see an object that implement an interface but that isn't a class instance.COM objects that come from code not written in D.
Dec 02 2012
On Monday, 3 December 2012 at 01:12:41 UTC, Walter Bright wrote:On 12/3/2012 9:17 AM, deadalnix wrote:OK that make sense. I have to think about it.I'm still waiting to see an object that implement aninterface but thatisn't a class instance.COM objects that come from code not written in D.
Dec 02 2012
On Monday, 3 December 2012 at 06:45:42 UTC, deadalnix wrote:On Monday, 3 December 2012 at 01:12:41 UTC, Walter Bright wrote:When coding against interfaces, it is always a good decision not to try to get back the object. The main idea about using interfaces in first place is to have behavior independent of whatever class might implement it. If someone is trying to get back the implementation of a given interface, it is because the design is not sound in first place. -- PauloOn 12/3/2012 9:17 AM, deadalnix wrote:OK that make sense. I have to think about it.I'm still waiting to see an object that implement aninterface but thatisn't a class instance.COM objects that come from code not written in D.
Dec 03 2012
On 2012-12-03 11:20, Paulo Pinto wrote:When coding against interfaces, it is always a good decision not to try to get back the object. The main idea about using interfaces in first place is to have behavior independent of whatever class might implement it. If someone is trying to get back the implementation of a given interface, it is because the design is not sound in first place.Well, one would might think that this would work: interface I {} class A : I {} void main () { I i = new A; Object o = i; } But it doesn't. -- /Jacob Carlborg
Dec 03 2012
On Monday, 3 December 2012 at 13:50:45 UTC, Jacob Carlborg wrote:On 2012-12-03 11:20, Paulo Pinto wrote:Object does not implement interface I, so why should interface instance be implicitly converted to it? It even should not be implicitly convertible to class if that class implements interface. However it is possible to use cast. TDPL and dlang.org say almost nothing about it, but current investigated dmd behavior (http://dpaste.dzfl.pl/84637416) makes sense: it allows convenient conversion when it should happen, protects from poor implicit conversion which should not happen, but still allows to do what you want if you assume you are right. If you not, dmd punish you with segfault.When coding against interfaces, it is always a good decision not to try to get back the object. The main idea about using interfaces in first place is to have behavior independent of whatever class might implement it. If someone is trying to get back the implementation of a given interface, it is because the design is not sound in first place.Well, one would might think that this would work: interface I {} class A : I {} void main () { I i = new A; Object o = i; } But it doesn't.
Dec 03 2012
On 2012-12-03 15:41, Maxim Fomin wrote:Object does not implement interface I, so why should interface instance be implicitly converted to it? It even should not be implicitly convertible to class if that class implements interface. However it is possible to use cast.Because Object is the root of the class hierarchy. That's how it works in Java, for example. It's just because of these COM interfaces, that are not D interfaces, that we have this behavior. -- /Jacob Carlborg
Dec 03 2012
On 2012-12-03 16:51, Jacob Carlborg wrote:Because Object is the root of the class hierarchy. That's how it works in Java, for example. It's just because of these COM interfaces, that are not D interfaces, that we have this behavior.Note, I'm not saying that an interface should be implicitly converted to any class, only to Object. -- /Jacob Carlborg
Dec 03 2012
On 12/4/2012 2:52 AM, Jacob Carlborg wrote:Note, I'm not saying that an interface should be implicitly converted to any class, only to Object.But not all interfaces come from Objects.
Dec 03 2012
On Monday, 3 December 2012 at 20:59:24 UTC, Walter Bright wrote:On 12/4/2012 2:52 AM, Jacob Carlborg wrote:So I thought about all that. typeid is about runtime type detection. As all interfaces are not coming from object, it is definitively an issue to resolve them as object sometime. However, keeping tied to the static type when runtime typeid is asked for is a but sad. But interfaces that don't resolve as object are well know at compile time. So isn't it possible to resolve all interfaces that we know are objects into object's typeid ? After all, this is what typeid is about.Note, I'm not saying that an interface should be implicitly converted to any class, only to Object.But not all interfaces come from Objects.
Dec 03 2012
On 12/4/2012 8:07 AM, deadalnix wrote:On Monday, 3 December 2012 at 20:59:24 UTC, Walter Bright wrote:I really don't know what issue you're trying to solve here. The typeid's work fine - and interfaces are not objects. Having the typeid for an interface be an object means you cannot compare typeids of one interface to another interface. And, my feeling is that if your code needs to implicitly convert interfaces to objects, or even know that an interface instance is implemented by a particular object, your program design is broken and is missing the point of what interfaces are.On 12/4/2012 2:52 AM, Jacob Carlborg wrote:So I thought about all that. typeid is about runtime type detection. As all interfaces are not coming from object, it is definitively an issue to resolve them as object sometime. However, keeping tied to the static type when runtime typeid is asked for is a but sad. But interfaces that don't resolve as object are well know at compile time. So isn't it possible to resolve all interfaces that we know are objects into object's typeid ? After all, this is what typeid is about.Note, I'm not saying that an interface should be implicitly converted to any class, only to Object.But not all interfaces come from Objects.
Dec 03 2012
On Monday, 3 December 2012 at 21:53:47 UTC, Walter Bright wrote:I really don't know what issue you're trying to solve here. The typeid's work fine - and interfaces are not objects. Having the typeid for an interface be an object means you cannot compare typeids of one interface to another interface.You can't instantiate interface. So an underlying type MUST exist. The whole point of typeid on expression is to discover what is the dynamic type of things, otherwize you'd be using typeid(type) not typeid(expression).And, my feeling is that if your code needs to implicitly convert interfaces to objects, or even know that an interface instance is implemented by a particular object, your program design is broken and is missing the point of what interfaces are.The same apply to object in general, and still D does it and for good reason (you'll find that few cases where it is actually useful and not a design flaw).
Dec 03 2012
On Monday, 3 December 2012 at 23:53:26 UTC, deadalnix wrote:On Monday, 3 December 2012 at 21:53:47 UTC, Walter Bright wrote:You cannot create interface instance with new operator because interface object is not valid until it is actually some class instance. But this does not mean neither that typeid operator for interfaces should return dynamic type nor that interface can be implicitly converted to Object - because interface instance may be invalid: import std.stdio; interface I { } void main() { I i; // should be implicitly converted Object o = cast(Object)i; writeln(typeid(o)); } and because presence of interface does not necessarily mean that some class has implemented it. This makes casting interfaces to object unsafe operation that better should require explicit cast.I really don't know what issue you're trying to solve here. The typeid's work fine - and interfaces are not objects. Having the typeid for an interface be an object means you cannot compare typeids of one interface to another interface.You can't instantiate interface. So an underlying type MUST exist. The whole point of typeid on expression is to discover what is the dynamic type of things, otherwize you'd be using typeid(type) not typeid(expression).
Dec 03 2012
On Tuesday, 4 December 2012 at 07:38:31 UTC, Maxim Fomin wrote:On Monday, 3 December 2012 at 23:53:26 UTC, deadalnix wrote:Given my experience with the interface concept in several OO languages that implement it, I would say that you never want to know what object was given to you. The whole point of interfaces is to have some form of multiple inheritance in single inheritance languages. So you *really* don't want to cast interfaces to objects. I can't think of a single reason this makes sense, other than work around bad designs. -- PauloOn Monday, 3 December 2012 at 21:53:47 UTC, Walter Bright wrote:You cannot create interface instance with new operator because interface object is not valid until it is actually some class instance. But this does not mean neither that typeid operator for interfaces should return dynamic type nor that interface can be implicitly converted to Object - because interface instance may be invalid: import std.stdio; interface I { } void main() { I i; // should be implicitly converted Object o = cast(Object)i; writeln(typeid(o)); } and because presence of interface does not necessarily mean that some class has implemented it. This makes casting interfaces to object unsafe operation that better should require explicit cast.I really don't know what issue you're trying to solve here. The typeid's work fine - and interfaces are not objects. Having the typeid for an interface be an object means you cannot compare typeids of one interface to another interface.You can't instantiate interface. So an underlying type MUST exist. The whole point of typeid on expression is to discover what is the dynamic type of things, otherwize you'd be using typeid(type) not typeid(expression).
Dec 04 2012
On Tuesday, 4 December 2012 at 07:38:31 UTC, Maxim Fomin wrote:On Monday, 3 December 2012 at 23:53:26 UTC, deadalnix wrote:The above is a perfectly safe conversion. The variable i is _a reference_ to instance of I. since it was not assigned any class instance that implements I, it is initialized as _null_. In the example above: (o is null && typeid(o) == typeid(Object))On Monday, 3 December 2012 at 21:53:47 UTC, Walter Bright wrote:You cannot create interface instance with new operator because interface object is not valid until it is actually some class instance. But this does not mean neither that typeid operator for interfaces should return dynamic type nor that interface can be implicitly converted to Object - because interface instance may be invalid: import std.stdio; interface I { } void main() { I i; // should be implicitly converted Object o = cast(Object)i; writeln(typeid(o)); } and because presence of interface does not necessarily mean that some class has implemented it. This makes casting interfaces to object unsafe operation that better should require explicit cast.I really don't know what issue you're trying to solve here. The typeid's work fine - and interfaces are not objects. Having the typeid for an interface be an object means you cannot compare typeids of one interface to another interface.You can't instantiate interface. So an underlying type MUST exist. The whole point of typeid on expression is to discover what is the dynamic type of things, otherwize you'd be using typeid(type) not typeid(expression).
Dec 04 2012
On 2012-12-03 21:59, Walter Bright wrote:But not all interfaces come from Objects.No, but those are statically known. -- /Jacob Carlborg
Dec 03 2012
On Monday, 3 December 2012 at 20:59:24 UTC, Walter Bright wrote:On 12/4/2012 2:52 AM, Jacob Carlborg wrote:IMO this is a design mistake - the special case is preferred over the common case which goes against the D philosophy of making the common case easy and the special case possible. All COM instances are known at _compile_time_ as they're all required to inherit from a special IUnknown interface so the compiler _knows_ if indeed an interface represents a COM instance or not. This can be used to handle this special case differently. Interface i = new Class(); Object o = i; // should work for regular interfaces The compiler can issue a compile-time error if i is COM since this is known at compile type.Note, I'm not saying that an interface should be implicitly converted to any class, only to Object.But not all interfaces come from Objects.
Dec 04 2012
On 2012-12-04 13:15, foobar wrote:IMO this is a design mistake - the special case is preferred over the common case which goes against the D philosophy of making the common case easy and the special case possible. All COM instances are known at _compile_time_ as they're all required to inherit from a special IUnknown interface so the compiler _knows_ if indeed an interface represents a COM instance or not. This can be used to handle this special case differently. Interface i = new Class(); Object o = i; // should work for regular interfaces The compiler can issue a compile-time error if i is COM since this is known at compile type.Exactly, I couldn't agree more. -- /Jacob Carlborg
Dec 04 2012
On Monday, 3 December 2012 at 15:52:24 UTC, Jacob Carlborg wrote:On 2012-12-03 16:51, Jacob Carlborg wrote:And what happens if nobody implements an interface? import std.stdio; interface I { } class A { } void main() { I i; // assume this is implicit Object o = cast(Object)i; writeln(typeid(o)); } Safe conversion class to interface requires two conditions: 1a) that class implements interface 1b) if you try to use interface variable, it must be an allocated class instance Safe conversion to Object requires: 2a) somebody in class hierarchy implements interface 2b) interface instance is actually allocated class instance It is possible to check 1a) but impossible in general case to check 2a). Also the first is design feature while the second is design abuse. And if there is need for getting runtime type of interface through typeid() it is always possible to use cast: import std.stdio; interface I { } class A : I { } void main() { A a = new A; I i = a; Object o = cast(Object)i; writeln(typeid(o)); // A }Because Object is the root of the class hierarchy. That's how it works in Java, for example. It's just because of these COM interfaces, that are not D interfaces, that we have this behavior.Note, I'm not saying that an interface should be implicitly converted to any class, only to Object.
Dec 04 2012
On Tuesday, 4 December 2012 at 08:22:36 UTC, Maxim Fomin wrote:On Monday, 3 December 2012 at 15:52:24 UTC, Jacob Carlborg wrote:The same as abstract classes : you can get the typeid by looking at it throw child's typeid or typeid(type). typeid(expression) will never return them because they can't be instantiated.On 2012-12-03 16:51, Jacob Carlborg wrote:And what happens if nobody implements an interface?Because Object is the root of the class hierarchy. That's how it works in Java, for example. It's just because of these COM interfaces, that are not D interfaces, that we have this behavior.Note, I'm not saying that an interface should be implicitly converted to any class, only to Object.
Dec 04 2012
On 2012-12-04 09:22, Maxim Fomin wrote:And what happens if nobody implements an interface? import std.stdio; interface I { } class A { } void main() { I i; // assume this is implicit Object o = cast(Object)i; writeln(typeid(o)); }You get a segmentation fault since both "i" and "o" are null.Safe conversion class to interface requires two conditions: 1a) that class implements interface 1b) if you try to use interface variable, it must be an allocated class instance Safe conversion to Object requires: 2a) somebody in class hierarchy implements interface 2b) interface instance is actually allocated class instanceYou cannot really get an instance of an interface without having a class implementing it. That is, without inserting any explicit casts, which works: interface I { } class A { } void main() { A a = new A; I i = cast(I) a; Object o = cast(Object)i; writeln(typeid(a)); // A }It is possible to check 1a) but impossible in general case to check 2a). Also the first is design feature while the second is design abuse.I don't understand why it wouldn't be safe to allow implicit casts of interfaces to Object. If I want to call toString, why should I need to insert an explicit cast to Object just because I have an interface? -- /Jacob Carlborg
Dec 04 2012
On Tuesday, 4 December 2012 at 12:26:53 UTC, Jacob Carlborg wrote:On 2012-12-04 09:22, Maxim Fomin wrote:If you want to call toSring, it should be part of the interface specification, as simple as that. Interfaces are like contracts which state what is to be expected of a certain type. -- PauloAnd what happens if nobody implements an interface? import std.stdio; interface I { } class A { } void main() { I i; // assume this is implicit Object o = cast(Object)i; writeln(typeid(o)); }You get a segmentation fault since both "i" and "o" are null.Safe conversion class to interface requires two conditions: 1a) that class implements interface 1b) if you try to use interface variable, it must be an allocated class instance Safe conversion to Object requires: 2a) somebody in class hierarchy implements interface 2b) interface instance is actually allocated class instanceYou cannot really get an instance of an interface without having a class implementing it. That is, without inserting any explicit casts, which works: interface I { } class A { } void main() { A a = new A; I i = cast(I) a; Object o = cast(Object)i; writeln(typeid(a)); // A }It is possible to check 1a) but impossible in general case to check 2a). Also the first is design feature while the second is design abuse.I don't understand why it wouldn't be safe to allow implicit casts of interfaces to Object. If I want to call toString, why should I need to insert an explicit cast to Object just because I have an interface?
Dec 04 2012
On Tuesday, 4 December 2012 at 12:30:29 UTC, Paulo Pinto wrote:On Tuesday, 4 December 2012 at 12:26:53 UTC, Jacob Carlborg wrote:Generally speaking you are right. But specifically regarding toString, what would you suggest? Should each and every Interface have a toString method? Should we have an IObject Interface that all classes are required to explicitly inherit? The purpose of having a root Object class is to define the _common interface of all objects_. Why else have such a class in the first place? Requiring an explicit cast to Object makes sense only in a no-single-root design such as the one in c++ which D sensibly chose not to copy. We can have a separate debate what should the root Object define, but there should not be a requirement to explicitly cast any object to it.On 2012-12-04 09:22, Maxim Fomin wrote:If you want to call toSring, it should be part of the interface specification, as simple as that. Interfaces are like contracts which state what is to be expected of a certain type. -- PauloAnd what happens if nobody implements an interface? import std.stdio; interface I { } class A { } void main() { I i; // assume this is implicit Object o = cast(Object)i; writeln(typeid(o)); }You get a segmentation fault since both "i" and "o" are null.Safe conversion class to interface requires two conditions: 1a) that class implements interface 1b) if you try to use interface variable, it must be an allocated class instance Safe conversion to Object requires: 2a) somebody in class hierarchy implements interface 2b) interface instance is actually allocated class instanceYou cannot really get an instance of an interface without having a class implementing it. That is, without inserting any explicit casts, which works: interface I { } class A { } void main() { A a = new A; I i = cast(I) a; Object o = cast(Object)i; writeln(typeid(a)); // A }It is possible to check 1a) but impossible in general case to check 2a). Also the first is design feature while the second is design abuse.I don't understand why it wouldn't be safe to allow implicit casts of interfaces to Object. If I want to call toString, why should I need to insert an explicit cast to Object just because I have an interface?
Dec 04 2012
On Tuesday, 4 December 2012 at 13:07:59 UTC, foobar wrote:On Tuesday, 4 December 2012 at 12:30:29 UTC, Paulo Pinto wrote:Yes for each interface where you intend to call toString().On Tuesday, 4 December 2012 at 12:26:53 UTC, Jacob Carlborg wrote:Generally speaking you are right. But specifically regarding toString, what would you suggest? Should each and every Interface have a toString method?On 2012-12-04 09:22, Maxim Fomin wrote:If you want to call toSring, it should be part of the interface specification, as simple as that. Interfaces are like contracts which state what is to be expected of a certain type. -- PauloAnd what happens if nobody implements an interface? import std.stdio; interface I { } class A { } void main() { I i; // assume this is implicit Object o = cast(Object)i; writeln(typeid(o)); }You get a segmentation fault since both "i" and "o" are null.Safe conversion class to interface requires two conditions: 1a) that class implements interface 1b) if you try to use interface variable, it must be an allocated class instance Safe conversion to Object requires: 2a) somebody in class hierarchy implements interface 2b) interface instance is actually allocated class instanceYou cannot really get an instance of an interface without having a class implementing it. That is, without inserting any explicit casts, which works: interface I { } class A { } void main() { A a = new A; I i = cast(I) a; Object o = cast(Object)i; writeln(typeid(a)); // A }It is possible to check 1a) but impossible in general case to check 2a). Also the first is design feature while the second is design abuse.I don't understand why it wouldn't be safe to allow implicit casts of interfaces to Object. If I want to call toString, why should I need to insert an explicit cast to Object just because I have an interface?Should we have an IObject Interface that all classes are required to explicitly inherit? The purpose of having a root Object class is to define the _common interface of all objects_. Why else have such a class in the first place?For languages without generics where you need a common base class to place in containers.Requiring an explicit cast to Object makes sense only in a no-single-root design such as the one in c++ which D sensibly chose not to copy. We can have a separate debate what should the root Object define, but there should not be a requirement to explicitly cast any object to it.The whole point of interfaces is to have explicit dependencies of methods, properties, variables across the inheritance tree. Actually there was a discussion some months ago about what methods still made sense to expose via object, given D's templates. -- Paulo
Dec 04 2012
On Tuesday, 4 December 2012 at 13:47:39 UTC, Paulo Pinto wrote:That's a lot of duplication considering D already provides this in Object.Generally speaking you are right. But specifically regarding toString, what would you suggest? Should each and every Interface have a toString method?Yes for each interface where you intend to call toString().That's only one reason. Other reasons are to provide a common interface for all objects. Anyway, we are discussing the current D design and not other possible designs such as the one in C++.Should we have an IObject Interface that all classes are required to explicitly inherit? The purpose of having a root Object class is to define the _common interface of all objects_. Why else have such a class in the first place?For languages without generics where you need a common base class to place in containers.Given D's _current_ design, all objects should implicitly cast to Object. It's plain common sense - If we have a root class that all other classes inherit from than it logically follows that all class instances can be implicitly & safely converted back to that root class (Object). What you are arguing is whether the current design of D of defining Object makes sense in the first place. I'm arguing that _given the current design_ the language is inconsistent and has a design flaw.Requiring an explicit cast to Object makes sense only in a no-single-root design such as the one in c++ which D sensibly chose not to copy. We can have a separate debate what should the root Object define, but there should not be a requirement to explicitly cast any object to it.The whole point of interfaces is to have explicit dependencies of methods, properties, variables across the inheritance tree. Actually there was a discussion some months ago about what methods still made sense to expose via object, given D's templates. -- Paulo
Dec 04 2012
On Tuesday, December 04, 2012 17:35:23 foobar wrote:That's a lot of duplication considering D already provides this in Object.Though per the last major discussion on const-correctness and Object, it's likely that toString, toHash, opCmp, and opEquals will be removed from Object, in which case you'd need a derived class which implemented them to use any of them. - Jonathan m Davis
Dec 04 2012
On Tuesday, 4 December 2012 at 18:41:14 UTC, Jonathan M Davis wrote:On Tuesday, December 04, 2012 17:35:23 foobar wrote:In other words, the plan is to pretty much deprecate Object? I hope there would be appropriate replacement before this happens. Users should be able to have a standardized API and a default implementation for these methods. Is phobos going to introduce interface such as Printable, Comparable, etc.. ? (names tentative, I'm more worried about the semantics).That's a lot of duplication considering D already provides this in Object.Though per the last major discussion on const-correctness and Object, it's likely that toString, toHash, opCmp, and opEquals will be removed from Object, in which case you'd need a derived class which implemented them to use any of them. - Jonathan m Davis
Dec 05 2012
On Wednesday, December 05, 2012 15:11:55 foobar wrote:On Tuesday, 4 December 2012 at 18:41:14 UTC, Jonathan M Davis wrote:No. The plan is not to deprecate Object. The reality is that those functions don't need to be on Object in D, because all of the runtime stuff that relies have to put them on Object and operate through Object. What we have currently (and templates weren't as good in D1, possibly making those functions necessary there). And having those functions on Object has created a lot of problems with regards to stuff like const. If they're there, they have to be const so that you can compare const objects, but given how D's const works, that then make certain idioms impossible in classes (e.g. lazy loading member variables and caching). const needs to work, but we can't force it on people, and putting it on Object forces it on people. Rather, it's perfectly possible for only derived classes to have those functions. They can then use the function attributes that match what they need, and stuff like druntime's opEquals or AAs will just be appropriately tempatized and work with the derived classes without needing to have any of that on Object. There's really no need to have any of that on Object. I'd have to go digging through the archives to find the last discussion on const-correctness where this was discussed in some detail, but that's the gist of it. Putting those functions on Object causes a lot of problems with regards to function attributes, and templates make actually putting those functions on Object unnecessary. - Jonathan M DavisOn Tuesday, December 04, 2012 17:35:23 foobar wrote:In other words, the plan is to pretty much deprecate Object? I hope there would be appropriate replacement before this happens. Users should be able to have a standardized API and a default implementation for these methods. Is phobos going to introduce interface such as Printable, Comparable, etc.. ? (names tentative, I'm more worried about the semantics).That's a lot of duplication considering D already provides this in Object.Though per the last major discussion on const-correctness and Object, it's likely that toString, toHash, opCmp, and opEquals will be removed from Object, in which case you'd need a derived class which implemented them to use any of them. - Jonathan m Davis
Dec 05 2012
On Wednesday, 5 December 2012 at 16:21:55 UTC, Jonathan M Davis wrote:On Wednesday, December 05, 2012 15:11:55 foobar wrote:But these are the methods of Object. So even if Object itself remains it looses its meaning. So are we going to keep Object just for backwards compatibility? Is there any point left keeping the single root design?On Tuesday, 4 December 2012 at 18:41:14 UTC, Jonathan M Davis wrote:No. The plan is not to deprecate Object. The reality is that those functions don't need to be on Object in D, because all of the runtime stuff that relies on them can (and really should) be templatized, whereas in Java have to put them on Object and operate through Object. What we have currently have with Object in D is a case of having copied too much from (and templates weren't as good in D1, possibly making those functions necessary there). And having those functions on Object has created a lot of problems with regards to stuff like const. If they're there, they have to be const so that you can compare const objects, but given how D's const works, that then make certain idioms impossible in classes (e.g. lazy loading member variables and caching). const needs to work, but we can't force it on people, and putting it on Object forces it on people. Rather, it's perfectly possible for only derived classes to have those functions. They can then use the function attributes that match what they need, and stuff like druntime's opEquals or AAs will just be appropriately tempatized and work with the derived classes without needing to have any of that on Object. There's really no need to have any of that on Object. I'd have to go digging through the archives to find the last discussion on const-correctness where this was discussed in some detail, but that's the gist of it. Putting those functions on Object causes a lot of problems with regards to function attributes, and templates make actually putting those functions on Object unnecessary. - Jonathan M DavisOn Tuesday, December 04, 2012 17:35:23 foobar wrote:In other words, the plan is to pretty much deprecate Object? I hope there would be appropriate replacement before this happens. Users should be able to have a standardized API and a default implementation for these methods. Is phobos going to introduce interface such as Printable, Comparable, etc.. ? (names tentative, I'm more worried about the semantics).That's a lot of duplication considering D already provides this in Object.Though per the last major discussion on const-correctness and Object, it's likely that toString, toHash, opCmp, and opEquals will be removed from Object, in which case you'd need a derived class which implemented them to use any of them. - Jonathan m Davis
Dec 06 2012
On Thursday, December 06, 2012 12:03:14 foobar wrote:But these are the methods of Object. So even if Object itself remains it looses its meaning. So are we going to keep Object just for backwards compatibility? Is there any point left keeping the single root design?It's would still be perfectly possible to pass around Object if you wanted to. You just couldn't call much on it without casting it to something else first. Perhaps there's less reason to have it, but no one ever suggested that we get rid of it. Having those functions on Object has harmed us. Having a common base type hasn't. But much as it was decided on, nothing has happened yet, so who knows how the transition will be done. - Jonathan M Davis
Dec 06 2012
On Thursday, 6 December 2012 at 11:03:15 UTC, foobar wrote:But these are the methods of Object. So even if Object itself remains it looses its meaning. So are we going to keep Object just for backwards compatibility? Is there any point left keeping the single root design?I don't see any major drawback in keeping Object. What are the drawbacks ?
Dec 06 2012
On Tuesday, 4 December 2012 at 18:41:14 UTC, Jonathan M Davis wrote:On Tuesday, December 04, 2012 17:35:23 foobar wrote:In other words, the plan is to pretty much deprecate Object? I hope there would be appropriate replacement before this happens. Users should be able to have a standardized API and a default implementation for these methods. Is phobos going to introduce interface such as Printable, Comparable, etc.. ? (names tentative, I'm more worried about the semantics).That's a lot of duplication considering D already provides this in Object.Though per the last major discussion on const-correctness and Object, it's likely that toString, toHash, opCmp, and opEquals will be removed from Object, in which case you'd need a derived class which implemented them to use any of them. - Jonathan m Davis
Dec 05 2012
On Tuesday, 4 December 2012 at 18:41:14 UTC, Jonathan M Davis wrote:On Tuesday, December 04, 2012 17:35:23 foobar wrote:In other words, the plan is to pretty much deprecate Object? I hope there would be appropriate replacement before this happens. Users should be able to have a standardized API and a default implementation for these methods. Is phobos going to introduce interfaces such as Printable, Comparable, etc.. ? (names tentative, I'm more worried about the semantics).That's a lot of duplication considering D already provides this in Object.Though per the last major discussion on const-correctness and Object, it's likely that toString, toHash, opCmp, and opEquals will be removed from Object, in which case you'd need a derived class which implemented them to use any of them. - Jonathan m Davis
Dec 05 2012