www.digitalmars.com         C & C++   DMDScript  

D - Auto-read only getter

reply Russ Lewis <russ deming-os.org> writes:
I like the getter/setter semantics you've defined.  However, they have a
small problem that I've wanted solved in C++.  Specifically, there are a
number of properties of my classes that I want other classes to be able
to read but not to change.  D allows this with getters and setters:



class Foo
{
   int bar;
public:
   int bar() { return bar; };
};



I'm going to be typing that *many* times in my code.  I suggest that we
add 'read' and 'write' (or 'get' and 'set') keywords:



class Foo
{
   int baz;  // this is totally private
public read protected write:
   int bar;   // this is publicly settable but 'protected' on writes
};



I'm not sure what might be the best syntax:

public read protected write:
public(read) protected(write):
public(r) protected(w):
r=public w=protected:
public,protected:

I'm also not sure if you should be able to abbreviate:

public read:
   could be equivalent to
public read protected write:
Aug 21 2001
next sibling parent reply "Sheldon Simms" <sheldon semanticedge.com> writes:
Im Artikel <3B82D6BD.CCA245D9 deming-os.org> schrieb "Russ Lewis"
<russ deming-os.org>:

 I like the getter/setter semantics you've defined.  However, they have a
 small problem that I've wanted solved in C++.  Specifically, there are a
 number of properties of my classes that I want other classes to be able
 to read but not to change.  D allows this with getters and setters:
 
 class Foo
 {
    int bar;
 public:
    int bar() { return bar; };
 };
 

 add 'read' and 'write' (or 'get' and 'set') keywords:
 
 class Foo
 {
    int baz;  // this is totally private
 public read protected write:
    int bar;   // this is publicly settable but 'protected' on writes
 };

I made a similar suggestion a few days ago: class Foo { int baz; // private protected: int bar; // protected, in general public: int bar(); // bar-getter is public and automatically generated } Or if you don't like the automatically generated stuff class Foo { int baz; // private protected: int bar; // protected, in general public: int bar () { return bar; } // bar-getter is public } This seems to do what you want and be possible with the current D spec. -- Sheldon Simms / sheldon semanticedge.com
Aug 21 2001
parent reply Russ Lewis <russ deming-os.org> writes:
Sheldon Simms wrote:

 class Foo
 {
   int baz; // private
 protected:
   int bar; // protected, in general
 public:
   int bar(); // bar-getter is public and automatically generated
 }

 Or if you don't like the automatically generated stuff

This is almost exactly what I posted in my original post. Yes, it works, but I'm suggesting that it could be made even quicker.
Aug 21 2001
parent reply "Sheldon Simms" <sheldon semanticedge.com> writes:
Im Artikel <3B82E4C0.EFAD69E4 deming-os.org> schrieb "Russ Lewis"
<russ deming-os.org>:

 Sheldon Simms wrote:
 
 class Foo
 {
   int baz; // private
 protected:
   int bar; // protected, in general
 public:
   int bar(); // bar-getter is public and automatically generated
 }

 Or if you don't like the automatically generated stuff

This is almost exactly what I posted in my original post. Yes, it works, but I'm suggesting that it could be made even quicker.

Why is is not just as quick this way? Function call semantics don't necessarily mean that a function call is actually made. -- Sheldon Simms / sheldon semanticedge.com
Aug 21 2001
parent Russ Lewis <russ deming-os.org> writes:
Sheldon Simms wrote:

 Im Artikel <3B82E4C0.EFAD69E4 deming-os.org> schrieb "Russ Lewis"
 <russ deming-os.org>:

 Sheldon Simms wrote:

 class Foo
 {
   int baz; // private
 protected:
   int bar; // protected, in general
 public:
   int bar(); // bar-getter is public and automatically generated
 }

 Or if you don't like the automatically generated stuff

This is almost exactly what I posted in my original post. Yes, it works, but I'm suggesting that it could be made even quicker.

Why is is not just as quick this way? Function call semantics don't necessarily mean that a function call is actually made.

Misunderstanding here. Either way will compile to identical code (presumably). What I meant was that it would be quicker to type, i.e. syntax sugar.
Aug 21 2001
prev sibling parent reply Charles Hixson <charleshixsn earthlink.net> writes:
Russ Lewis wrote:
 I like the getter/setter semantics you've defined.  However, they have a
 small problem that I've wanted solved in C++.  Specifically, there are a
 number of properties of my classes that I want other classes to be able
 to read but not to change.  D allows this with getters and setters:
 
 
 
 class Foo
 {
    int bar;
 public:
    int bar() { return bar; };
 };
 
 
 
 I'm going to be typing that *many* times in my code.  I suggest that we
 add 'read' and 'write' (or 'get' and 'set') keywords:
 
 
 
 class Foo
 {
    int baz;  // this is totally private
 public read protected write:
    int bar;   // this is publicly settable but 'protected' on writes
 };
 
 
 
 I'm not sure what might be the best syntax:
 
 public read protected write:
 public(read) protected(write):
 public(r) protected(w):
 r=public w=protected:
 public,protected:
 
 I'm also not sure if you should be able to abbreviate:
 
 public read:
    could be equivalent to
 public read protected write:
 
 

I would prefer a "visible" tag to work in conjucntion with private and protected. It would only be a reserver word immediately following those two words, and would itself need to be followed by a colon, thus: private visible: char [5] name; char [] address; ... private: ... The "private visible" variables could be read externally, but not modified. The problem here is the usual one, if name can be read, how do you prevent the individual members (characters) of name from being changed? Do you use reference or cloning? One is insecure, and the other can get expensive. I don't like using intermediate functions, but they do deal with this problem (by letting the user decide), and I can't think of any better answer, except: Well, Ruby has read and set declarations that take a list of variables as their argument. These are basically just automatic function generators, but it looks rathe like this (with syntax modification): private: char [5] name; char[] address; ... protected: allowRead: name, address; ... which would allow name and address to be accessed via an auto-generated reader function as protected variables. This gives a bit more control than just a "private visible" declaration, but it still doesn't address the reference vs. copy problem, or rather it does. It says "This default action is available if you choose to use it. If you want something else, you'll need to do it yourself." These add a bit of convenience, but I'm not sure that they add enough to be worth the effort. (Of course, I don't know how much effort that would be...) A good choice would be one that allowed the clone vs. reference to be specified, and was also clean, easy to read, easy to parse, and easy to implement. A tall order. Big, do-everything languages tend to become unwieldy. When C++ first came out, I thought it a big improvement on C. I was especially taken by the "const" feature. "class" ... C++ has never seemed to to a good job of that. (see note below) Then templates got added. All of the various compilers got out of sync, and features kept getting added. Good features, most of them, taken individually, but they kept coming, and the language got larger, and larger. Now... well, I've tried Ada, I've tried Eiffel, I've tried C++. I'd like to use C++, because that's where all of the tools are. But it's so ugly, so unweildy. So I'm using Eiffel. I don't like it's inflexibility, but it's understandable in a reasonable amount of time. But I prefer Ada to C++. It has fewer wierd gotcha's. Most of them are right up front. <Note> They don't handle inheritance well. Eiffel, Java, Smalltalk, and Python all got a better handle on this. Even Ada did it better (and Ada95 was designed before C++). The problem is with virtual inheritance. Python does this best, Eiffel next best, then Java, and Ada. I think that LISP probably belongs here, but I don't really know it well enough to be sure. Then, near the very end, is C++. It's not the multiple inheritance. Eiffel has than, and so do Python, Lisp? and, sort of, Ada. Python took the simple answer (follow up the inheritance tree in a left hand branch first order), but it works. Eiffel took a much fancier approach. It allows a bit more than Python handles, and it works too. But truthfully, mixins and the auto-forwarding kind of delegation (see the Jamie preprocessor for Java, or Kiev, another JVM compiler) solve most of the problems that interfaces don't. Actually, given mixins and the aforementioned kind of delegation, a case could be made that interfaces were the only part of inheritance that was needed. And it might be a good case (you would use the delegation to replace inherited code with calls to its "ancestor"). But I don't know of any large programs developed with that model (no language that I know of makes it possible in a reasonable way). </Note>
Aug 22 2001
parent reply Russ Lewis <russ deming-os.org> writes:
Charles Hixson wrote:

 Russ Lewis wrote:
 I like the getter/setter semantics you've defined.  However, they have a
 small problem that I've wanted solved in C++.  Specifically, there are a
 number of properties of my classes that I want other classes to be able
 to read but not to change.  D allows this with getters and setters:



 class Foo
 {
    int bar;
 public:
    int bar() { return bar; };
 };



 I'm going to be typing that *many* times in my code.  I suggest that we
 add 'read' and 'write' (or 'get' and 'set') keywords:



 class Foo
 {
    int baz;  // this is totally private
 public read protected write:
    int bar;   // this is publicly settable but 'protected' on writes
 };



 I'm not sure what might be the best syntax:

 public read protected write:
 public(read) protected(write):
 public(r) protected(w):
 r=public w=protected:
 public,protected:

 I'm also not sure if you should be able to abbreviate:

 public read:
    could be equivalent to
 public read protected write:

I would prefer a "visible" tag to work in conjucntion with private and protected. It would only be a reserver word immediately following those two words, and would itself need to be followed by a colon, thus: private visible: char [5] name; char [] address; ... private: ... The "private visible" variables could be read externally, but not modified. The problem here is the usual one, if name can be read, how do you prevent the individual members (characters) of name from being changed? Do you use reference or cloning? One is insecure, and the other can get expensive. I don't like using intermediate functions, but they do deal with this problem (by letting the user decide), and I can't think of any better answer, except:

If it is read-only in your context, then the compiler could automatically return it as a const. You could copy it into your own array if you wanted to, or pass it as a (const) arg to other functions, but other than that you can't touch it.
Aug 22 2001
parent Charles Hixson <charleshixsn earthlink.net> writes:
Russ Lewis wrote:
 Charles Hixson wrote:
 
 
... 

return it as a const. You could copy it into your own array if you wanted to, or pass it as a (const) arg to other functions, but other than that you can't touch it.

pointer to a complex structure you couldn't change the structure, but you could change the 2nd level down. You could, e.g., take the address of the 5th element of an array, and change the contents of that address. Now D has some restrictions on pointers, so perhaps this isn't even possible, but it wasn't clearly impossible when I looked through the docs.
Aug 22 2001