www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Interface question

reply Charles D Hixson <charleshixsn earthlink.net> writes:
How should I write some code that would have an effect similar 
to what:
interface P
{  this(ulong ndx);
    ulong   fset();
}

would have if it were a legal construct?

The "constructor" needs to return an instance of the class 
that implements it.
Aug 28 2006
next sibling parent Reiner Pope <reiner.pope REMOVE.THIS.gmail.com> writes:
Charles D Hixson wrote:
 How should I write some code that would have an effect similar to what:
 interface P
 {  this(ulong ndx);
    ulong   fset();
 }
 
 would have if it were a legal construct?
 
 The "constructor" needs to return an instance of the class that 
 implements it.
I think you have to use the factory pattern: interface P { ulong fset(); } interface PFactory { P create(); }
Aug 28 2006
prev sibling parent reply BCS <BCS pathlink.com> writes:
Charles D Hixson wrote:
 How should I write some code that would have an effect similar to what:
 interface P
 {  this(ulong ndx);
    ulong   fset();
 }
 
 would have if it were a legal construct?
 
 The "constructor" needs to return an instance of the class that 
 implements it.
It strikes me as odd that you would want to do this. (I would have to see the usage though before I would say you shouldn't.) As I understand it the intention of Interfaces is that the underlying implementation is /totally/ hidden. If there is some action that the class needs to do at instancing time, then that should be apparent to the person coding the class and done by them. OTOH, if the "this" function is doing something like registering the class with some sort of global catalog, you might have need for something like that. However I would make the registration action associated with the catalog and not the Objects /****** Objects implementing P must register with the Catalog ******/ interface P { this(ulong); ulong fset(); } class Catalog { void Add(P); void Remove(P); } Catalog cat; class PO : P { ulong fset(){...} this(ulong f) { ... cat.Add(cast(P)this); } ~this() { cat.Remove(cast(P)this); } // OR /**************** ALWAYS registrar this class with the Catalog ****************/ }
Aug 29 2006
parent reply Charles D Hixson <charleshixsn earthlink.net> writes:
BCS wrote:
 Charles D Hixson wrote:
 How should I write some code that would have an effect similar to what:
 interface P
 {  this(ulong ndx);
    ulong   fset();
 }

 would have if it were a legal construct?

 The "constructor" needs to return an instance of the class that 
 implements it.
It strikes me as odd that you would want to do this. (I would have to see the usage though before I would say you shouldn't.) As I understand it the intention of Interfaces is that the underlying implementation is /totally/ hidden. If there is some action that the class needs to do at instancing time, then that should be apparent to the person coding the class and done by them. OTOH, if the "this" function is doing something like registering the class with some sort of global catalog, you might have need for something like that. However I would make the registration action associated with the catalog and not the Objects /****** Objects implementing P must register with the Catalog ******/ interface P { this(ulong); ulong fset(); } class Catalog { void Add(P); void Remove(P); } Catalog cat; class PO : P { ulong fset(){...} this(ulong f) { ... cat.Add(cast(P)this); } ~this() { cat.Remove(cast(P)this); } // OR /**************** ALWAYS registrar this class with the Catalog ****************/ }
That's essentially what I wanted to do (with variations...it's to disk, and the methods are save and restore)...but the interface is invalid! I guess what I'm going to need to do is derive everything from a common ancestral class...and that means that the derived classes CAN'T descend from anything else, *sigh*. The common ancestor will need to be a totally abstract class, so I thought an interface would be a better choice, but it looks like there's no way to make it work...because they've all got to implement a common constructor type, and the compiler has to KNOW that they do so.
Aug 29 2006
parent reply xs0 <xs0 xs0.com> writes:
 I guess what I'm going to need to do is derive everything from a common 
 ancestral class...and that means that the derived classes CAN'T descend 
 from anything else, *sigh*.  The common ancestor will need to be a 
 totally abstract class, so I thought an interface would be a better 
 choice, but it looks like there's no way to make it work...because 
 they've all got to implement a common constructor type, and the compiler 
 has to KNOW that they do so.
Hmm.. why exactly do you need a common constructor type? When you create an object, you must know its exact type (and constructors) anyway, so how does it matter? xs0
Aug 30 2006
next sibling parent reply Charles D Hixson <charleshixsn earthlink.net> writes:
xs0 wrote:
 
 I guess what I'm going to need to do is derive everything from a 
 common ancestral class...and that means that the derived classes CAN'T 
 descend from anything else, *sigh*.  The common ancestor will need to 
 be a totally abstract class, so I thought an interface would be a 
 better choice, but it looks like there's no way to make it 
 work...because they've all got to implement a common constructor type, 
 and the compiler has to KNOW that they do so.
Hmm.. why exactly do you need a common constructor type? When you create an object, you must know its exact type (and constructors) anyway, so how does it matter? xs0
I think maybe you're right. If so, then I probably can't do what I want to do in D. I'd been thinking that if I just worked ahead I'd be able to solve the problem of "somehow" using the thing that I'd created, if I could only create it. And I could refer to it from the ancestral reference. But I hadn't been able to figure out the details, so I was just trying to work my way forwards. But maybe I can't do it at all. (Well, this isn't literally true, of course. I could always define everything in terms of a Vector of bytes. But in so doing I give up most of what makes Computer Languages different from assembler.) I guess that means that it's back to Python. At least I can drop into Pyrex when I hit places that are performance bottlenecks. Or even into C. (I may truly dislike C with it's wild use of pointers, but it *is* possible. And it's about the same speed as D. [I don't really believe that shootout that says that D is faster. How *can* it be?])
Aug 30 2006
parent reply David Medlock <noone nowhere.com> writes:
Charles D Hixson wrote:
 xs0 wrote:
 
 I guess what I'm going to need to do is derive everything from a 
 common ancestral class...and that means that the derived classes 
 CAN'T descend from anything else, *sigh*.  The common ancestor will 
 need to be a totally abstract class, so I thought an interface would 
 be a better choice, but it looks like there's no way to make it 
 work...because they've all got to implement a common constructor 
 type, and the compiler has to KNOW that they do so.
Hmm.. why exactly do you need a common constructor type? When you create an object, you must know its exact type (and constructors) anyway, so how does it matter? xs0
I think maybe you're right. If so, then I probably can't do what I want to do in D. I'd been thinking that if I just worked ahead I'd be able to solve the problem of "somehow" using the thing that I'd created, if I could only create it. And I could refer to it from the ancestral reference. But I hadn't been able to figure out the details, so I was just trying to work my way forwards. But maybe I can't do it at all. (Well, this isn't literally true, of course. I could always define everything in terms of a Vector of bytes. But in so doing I give up most of what makes Computer Languages different from assembler.) I guess that means that it's back to Python. At least I can drop into Pyrex when I hit places that are performance bottlenecks. Or even into C. (I may truly dislike C with it's wild use of pointers, but it *is* possible. And it's about the same speed as D. [I don't really believe that shootout that says that D is faster. How *can* it be?])
(Ignore this if I am misreading you - David) I don't quite 'get' what you are trying to accomplish(not technically but in a design sense). Unless you are attempting to add compiled classes at runtime, I would be surprised if D could not accomplish what you are doing. To create an object which has a known constructor, use a template function/object....but there is a better way. Have your objects created with no argument constructors then configured using a common method. I have a text format(XML lite) I use in which each node is a 'constructor' for an object. Then the children of the node are passed to the config() method of the object. In this way I can have many similar objects which are combined in different ways. Is this close to what you are trying? -David
Aug 31 2006
next sibling parent Don Clugston <dac nospam.com.au> writes:
David Medlock wrote:
 Unless you are attempting to add compiled classes at runtime, I would be 
 surprised if D could not accomplish what you are doing.
And if you want to add compiled classes at runtime, you'll have to wait for DDL to be released -- but D will be able to accomplish it . <g>
Aug 31 2006
prev sibling parent reply Charles D Hixson <charleshixsn earthlink.net> writes:
David Medlock wrote:
 Charles D Hixson wrote:
 xs0 wrote:

...Ignore this if I am misreading you - David)
I don't quite 'get' what you are trying to accomplish(not technically but in a design sense). Unless you are attempting to add compiled classes at runtime, I would be surprised if D could not accomplish what you are doing. To create an object which has a known constructor, use a template function/object....but there is a better way. Have your objects created with no argument constructors then configured using a common method. I have a text format(XML lite) I use in which each node is a 'constructor' for an object. Then the children of the node are passed to the config() method of the object. In this way I can have many similar objects which are combined in different ways. Is this close to what you are trying? -David
The problem is, when the object is being read in from the file, the type of the object (on the file) determines the desired type of the created object. This appears to require the kind of run-time parsing that Python, Smalltalk, and Ruby have...and that D doesn't. I though I'd find away around it, but the only way I found involved storing everything in a common format (very inefficient) and making all the calls through multiple layers of indirection. If I do all THAT I might as well use Python, which at least doesn't fight me every step of the way. This just isn't something that D is designed to do. You CAN do it, but it's not natural to the language, so you need to fight it every step of the way. It would probably literally be more efficient to do this in Python, because in Python a lot of the steps that I need to do have been hand optimized by people who spent lots of time figuring the optimizations. It would *CERTAINLY* be lots easier. (I can create an object by merely unpickling it. Each class will just need to implement the __getstate__ and __setstate__ methods.) And if I try to do something with an object that hasn't been defined, I can catch it with an error handler, and figure out what I need to do differently...which I can do at run time, when I can examine what the class that I'm trying to handle is, but can't do at compile time, because the class hasn't been read in. (A lot of the time what I'll want to do is return a message that means, approximately "I'm sorry Dave, I can't do that." :-) I won't want to abort the process just because a particular kind of object can't do that. Your brain doesn't dump memory when you encounter a parsing error...you recover. You don't WANT a hard fault. And you can't predict all the kinds of sensory stimuli you will receive. I can't actually be too specific about what I need in detail, because I'm still feeling my way along. I was hoping to use D because it's much more efficient ... if you can fit your requirements into what it is designed to do. I was going to start off coding a simple neural net...which I could have done in D, but that is intended to be only a small part of the project...and the major part requires the additional flexibility in the handling of persistence. It's no big thing. Every language has it's strong points and it's weak point. D has more strong points than almost any other...but they don't fit *all* of my needs. (If the interface between D and Python is reactivated, I may end up recoding lots of modules that will fit the D model into D. I *FAR* prefer it to C, or even to Pyrex [my current fallback if I need more efficiency].)
Aug 31 2006
parent reply Reiner Pope <reiner.pope REMOVE.THIS.gmail.com> writes:
Charles D Hixson wrote:
 David Medlock wrote:
 Charles D Hixson wrote:
 xs0 wrote:

 ...Ignore this if I am misreading you - David)
I don't quite 'get' what you are trying to accomplish(not technically but in a design sense). Unless you are attempting to add compiled classes at runtime, I would be surprised if D could not accomplish what you are doing. To create an object which has a known constructor, use a template function/object....but there is a better way. Have your objects created with no argument constructors then configured using a common method. I have a text format(XML lite) I use in which each node is a 'constructor' for an object. Then the children of the node are passed to the config() method of the object. In this way I can have many similar objects which are combined in different ways. Is this close to what you are trying? -David
The problem is, when the object is being read in from the file, the type of the object (on the file) determines the desired type of the created object. This appears to require the kind of run-time parsing that Python, Smalltalk, and Ruby have...and that D doesn't. I though I'd find away around it, but the only way I found involved storing everything in a common format (very inefficient) and making all the calls through multiple layers of indirection. If I do all THAT I might as well use Python, which at least doesn't fight me every step of the way.
I don't understand quite what the difficulty is. If I understand you, you are deserializing objects, but you don't know what type they are. After you have deserialized them, you presumably want to do something with them. Am I right? So, presuming you want to do something with them, you can probably expect that all the objects can do such a thing. So we declare an interface: interface ObjectIveDeserialized { void doTheThingIWantThemToDo(); } Then, presuming that you will know all of the formats they can be in at compile-time (you must, else how could you write a parser for them?) then you just declare another interface: interface FileParser { ObjectIveDeserialized tryToDeserializeThisAndReturnNullIfIFail(Stream input); } Then you just have a list of all FileParsers and try each of them until one works. Maybe I'm completely misunderstanding you, but this doesn't seem to bad in D. How would you do it in a dynamic language like Python, Smalltalk, Ruby? Cheers, Reiner
Aug 31 2006
parent Charles D Hixson <charleshixsn earthlink.net> writes:
Reiner Pope wrote:
 Charles D Hixson wrote:
 David Medlock wrote:
 Charles D Hixson wrote:
 xs0 wrote:

 ...
I don't understand quite what the difficulty is. If I understand you, you are deserializing objects, but you don't know what type they are. After you have deserialized them, you presumably want to do something with them. Am I right? So, presuming you want to do something with them, you can probably expect that all the objects can do such a thing. So we declare an interface: interface ObjectIveDeserialized { void doTheThingIWantThemToDo(); } Then, presuming that you will know all of the formats they can be in at compile-time (you must, else how could you write a parser for them?) then you just declare another interface: interface FileParser { ObjectIveDeserialized tryToDeserializeThisAndReturnNullIfIFail(Stream input); } Then you just have a list of all FileParsers and try each of them until one works. Maybe I'm completely misunderstanding you, but this doesn't seem to bad in D. How would you do it in a dynamic language like Python, Smalltalk, Ruby? Cheers, Reiner
No, you can't know that all of the objects will be able to do what you want. You can EXPECT* that they'll be able to...but you won't be able to know. E.g. "In English you can verb any noun in the languge." works, but it's not true. You can only very ALMOST any noun in the language. So you've got to be able to check. And it's got to be a run-time check. More basically, I can't know ahead of time the class of the object that I'll be deserializing. I can have an expectation, but even that expectation is a run-time kind of thing. (Files have been known to get desynchronized, so I've got to be able to detect that what I got wasn't what I expected to get, and recover gracefully.) As for just HOW I'll use it...I haven't written that part yet, It involves requiring that each class implement two methods: __getstate__ and __setstate__ to specify how it should be saved and restored. Once it's restored, the language maintains a dict (think associated array) containing all the methods that it implements, so it's easy to check which of several alternatives can be used...if any. In D even the deserialization would require 20-50 times as much code per class. Similarly for the original serialization...because the Python language has included in it's library classes Pickle and bsddb. (As a first step I'm going to implement a Persistent class. I have the model of the shelve class to help me over any tricky spots, even though I intend to use a different database and a different basic approach. And, if I somehow couldn't, I could use the shelve class itself as a fallback Persistent class...though that would necessitate a redesign of the structure that I've been putting together. (Design first, code next...reiterate until done. If you don't design first, you won't know where you're going. If you don't code once you've got a chunk of the design complete, you won't know that your design is workable. So you've got to iterate.) * expecting that something is true means that you know it's usually true, but you also know that it sometimes isn't. If you can't computer even an approximate mean value, then you can't expect. If you can derive a standard deviation of zero, then you don't need to settle for expecting.
Sep 01 2006
prev sibling parent reply Paolo Invernizzi <arathorn NOSPAM_fastwebnet.it> writes:
So, the answer is that a constructor signature cannot be part of an 
interface?

We must use always the factory pattern?

---
Paolo

xs0 wrote:
 
 I guess what I'm going to need to do is derive everything from a 
 common ancestral class...and that means that the derived classes CAN'T 
 descend from anything else, *sigh*.  The common ancestor will need to 
 be a totally abstract class, so I thought an interface would be a 
 better choice, but it looks like there's no way to make it 
 work...because they've all got to implement a common constructor type, 
 and the compiler has to KNOW that they do so.
Hmm.. why exactly do you need a common constructor type? When you create an object, you must know its exact type (and constructors) anyway, so how does it matter? xs0
Aug 31 2006
parent reply xs0 <xs0 xs0.com> writes:
Paolo Invernizzi wrote:
 So, the answer is that a constructor signature cannot be part of an 
 interface?
 
 We must use always the factory pattern?
Well, as far as I can tell, you can't create a new object without a new expression, in which you need to state the exact type, so even if you could specify a constructor signature in an interface, you still couldn't generically create an object. If you could do it, though, what would the rest of the code look like? (I think you can't code around explicitly listing types somewhere, so I'm interested what you feel would be gained). xs0
Aug 31 2006
parent Paolo Invernizzi <arathorn NOSPAM_fastwebnet.it> writes:
xs0 wrote:

 Well, as far as I can tell, you can't create a new object without a new 
 expression, in which you need to state the exact type, so even if you 
 could specify a constructor signature in an interface, you still 
 couldn't generically create an object.
That's true...
 If you could do it, though, what would the rest of the code look like? 
 (I think you can't code around explicitly listing types somewhere, so 
 I'm interested what you feel would be gained).
That's true again... auto a = new SomeInterface is meaningless, as you cannot tell what 'concrete' class you need. My fault. --- Paolo
Aug 31 2006