www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - enforcing alias this on derived types

reply "JS" <js.mdnq gmail.com> writes:
I have an interface that I would like to make sure that any 
classes derived from it will use alias this, else it can 
potentially break code.

interface A(T)
{
      property T Value();
      property T Value(T value);
     // need to enforce alias _value this somehow
}

class B(T) : A!T
{
     private T _value;
      property T Value() { return _value; }
      property T Value(T value) { return value = _value; }
     alias _value this;
     // B must use alias this so B(T) behaves like type T
}
Jul 08 2013
next sibling parent "JS" <js.mdnq gmail.com> writes:
 interface A(T)
 {
      property T Value();
      property T Value(T value);
     // need to enforce alias Value this somehow
 }

 class B(T) : A!T
 {
     private T _value;
      property T Value() { return _value; }
      property T Value(T value) { return value = _value; }
alias Value this;
     // B must use alias this so B(T) behaves like type T
 }
Jul 08 2013
prev sibling next sibling parent reply "John Colvin" <john.loughran.colvin gmail.com> writes:
On Monday, 8 July 2013 at 08:59:16 UTC, JS wrote:
 I have an interface that I would like to make sure that any 
 classes derived from it will use alias this, else it can 
 potentially break code.

 interface A(T)
 {
      property T Value();
      property T Value(T value);
     // need to enforce alias _value this somehow
 }

 class B(T) : A!T
 {
     private T _value;
      property T Value() { return _value; }
      property T Value(T value) { return value = _value; }
     alias _value this;
     // B must use alias this so B(T) behaves like type T
 }
I can't think of a neat way to do this. However,if you don't mind a nasty solution: You can just force the derived class writer to write a function that checks. Even if they just put in a no-op, it acts as a very solid reminder that will also be visible to anyone else reading their code. struct S{} interface I { void checkForAliasThis(); } class A : I { void checkForAliasThis() { static assert(is(typeof(this) : S)); } S s; alias s this; } Most other solutions I tried failed because the compiler evaluates the check (e.g. out contracts) in the interface, which makes the check either semantically wrong, or statically false/failed.
Jul 08 2013
parent reply "John Colvin" <john.loughran.colvin gmail.com> writes:
On Monday, 8 July 2013 at 09:52:44 UTC, John Colvin wrote:
 Most other solutions I tried failed because the compiler 
 evaluates the check (e.g. out contracts) in the interface, 
 which makes the check either semantically wrong, or statically 
 false/failed.
Woops, should be "the contract exists in the scope of the interface", not "the compiler evaluates the check (e.g. out contracts) in the interface"
Jul 08 2013
parent reply "JS" <js.mdnq gmail.com> writes:
On Monday, 8 July 2013 at 09:55:29 UTC, John Colvin wrote:
 On Monday, 8 July 2013 at 09:52:44 UTC, John Colvin wrote:
 Most other solutions I tried failed because the compiler 
 evaluates the check (e.g. out contracts) in the interface, 
 which makes the check either semantically wrong, or statically 
 false/failed.
Woops, should be "the contract exists in the scope of the interface", not "the compiler evaluates the check (e.g. out contracts) in the interface"
Hopefully there is a cleaner way but this beats nothing... thanks.
Jul 08 2013
parent "John Colvin" <john.loughran.colvin gmail.com> writes:
On Monday, 8 July 2013 at 11:37:31 UTC, JS wrote:
 On Monday, 8 July 2013 at 09:55:29 UTC, John Colvin wrote:
 On Monday, 8 July 2013 at 09:52:44 UTC, John Colvin wrote:
 Most other solutions I tried failed because the compiler 
 evaluates the check (e.g. out contracts) in the interface, 
 which makes the check either semantically wrong, or 
 statically false/failed.
Woops, should be "the contract exists in the scope of the interface", not "the compiler evaluates the check (e.g. out contracts) in the interface"
Hopefully there is a cleaner way but this beats nothing... thanks.
There could be merit in adding more sophisticated requirements in base classes and interfaces. Currently, AFAIK there isn't one. inherited "static invariant() {}" would be one possibility, run at compile-time. Perhaps only run on classes that can be explicitly instantiated, but declared in any class/interface further up the inheritance tree. All static invariants would have to pass, in derived and base classes, i.e. it's a tighten-only contract like out. It's a unittest of sorts, but compile-time and fully class-aware.
Jul 08 2013
prev sibling parent Marco Leise <Marco.Leise gmx.de> writes:
Am Mon, 08 Jul 2013 10:59:14 +0200
schrieb "JS" <js.mdnq gmail.com>:

 I have an interface that I would like to make sure that any 
 classes derived from it will use alias this, else it can 
 potentially break code.
 
 interface A(T)
 {
       property T Value();
       property T Value(T value);
      // need to enforce alias _value this somehow
 }
 
 class B(T) : A!T
 {
      private T _value;
       property T Value() { return _value; }
       property T Value(T value) { return value = _value; }
      alias _value this;
      // B must use alias this so B(T) behaves like type T
 }
Interfaces only declare functions and have no state. What you do looks like you actually want to give the interface state through the "alias ... this" crutch. This is where you use abstract classes if possible: abstract class A(T) { private T _value; property T Value() { return _value; } property T Value(T value) { return value = _value; } alias _value this; } class B(T) : A!T { } I have only used "alias ... this" with structs and not tested this code. Generally I try to avoid mixing the realms of value types and class types in D like you are trying to. It gives me a bad gut feeling. In the OOP world I'd say, just use "obj.Value" everywhere you want your object to work like type T. -- Marco
Jul 08 2013