www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Why is this legal?

reply abad <abad.flt gmail.com> writes:
This works:

class Foo {
     protected void bar() {
         writeln("hello from foo");
     }
}

void main() {
     auto foo = new Foo;
     foo.bar();
}

Is this on purpose and what's the rationale?
Mar 29 2017
next sibling parent reply rikki cattermole <rikki cattermole.co.nz> writes:
On 29/03/2017 10:50 AM, abad wrote:
 This works:

 class Foo {
     protected void bar() {
         writeln("hello from foo");
     }
 }

 void main() {
     auto foo = new Foo;
     foo.bar();
 }

 Is this on purpose and what's the rationale?
http://dlang.org/spec/attribute.html#visibility_attributes "protected only applies inside classes (and templates as they can be mixed in) and means that a symbol can only be seen by members of the same module, or by a derived class. If accessing a protected instance member through a derived class member function, that member can only be accessed for the object instance which can be implicitly cast to the same type as ‘this’. protected module members are illegal."
Mar 29 2017
parent Jonathan M Davis via Digitalmars-d-learn writes:
On Wednesday, March 29, 2017 10:56:34 rikki cattermole via Digitalmars-d-
learn wrote:
 On 29/03/2017 10:50 AM, abad wrote:
 This works:

 class Foo {

     protected void bar() {

         writeln("hello from foo");

     }

 }

 void main() {

     auto foo = new Foo;
     foo.bar();

 }

 Is this on purpose and what's the rationale?
http://dlang.org/spec/attribute.html#visibility_attributes "protected only applies inside classes (and templates as they can be mixed in) and means that a symbol can only be seen by members of the same module, or by a derived class. If accessing a protected instance member through a derived class member function, that member can only be accessed for the object instance which can be implicitly cast to the same type as ‘this’. protected module members are illegal."
Yeah, everything in a module can see everything else in a module. It avoids needing to add the complication of friend function and classes like in C++. Basically, it's like everything within a module were declared as friends. If you want something to not have access to something else, then it's going to need to be put in a separate module. - Jonathan M Davis
Mar 29 2017
prev sibling next sibling parent abad <abad.flt gmail.com> writes:
Never mind, it's working OK if the class is defined in another 
module.
Mar 29 2017
prev sibling next sibling parent reply abad <abad.flt gmail.com> writes:
Related question, it seems that final methods are allowed in 
interfaces. Obviously you can't implement them anywhere, so is 
this also on purpose and on what rationale? :)
Mar 29 2017
next sibling parent reply abad <abad.flt gmail.com> writes:
On Wednesday, 29 March 2017 at 10:08:02 UTC, abad wrote:
 Related question, it seems that final methods are allowed in 
 interfaces. Obviously you can't implement them anywhere, so is 
 this also on purpose and on what rationale? :)
So actually it's just a question of not catching this mistake early, because obviously compilation will fail when any class tries to implement the interface so the end result is ok. Maybe it _could_ just disallow final methods altogether to catch the errors earlier. But very minor detail overall.
Mar 29 2017
parent reply Petar Kirov [ZombineDev] <petar.p.kirov gmail.com> writes:
On Wednesday, 29 March 2017 at 10:12:08 UTC, abad wrote:
 On Wednesday, 29 March 2017 at 10:08:02 UTC, abad wrote:
 Related question, it seems that final methods are allowed in 
 interfaces. Obviously you can't implement them anywhere, so is 
 this also on purpose and on what rationale? :)
So actually it's just a question of not catching this mistake early, because obviously compilation will fail when any class tries to implement the interface so the end result is ok. Maybe it _could_ just disallow final methods altogether to catch the errors earlier. But very minor detail overall.
The idea between `final` functions in interfaces is to provide a default non-overridable implementation. For example: interface Lockable { void lock(); void unlock(); alias Action = void delegate(); final void performLocked(Action action) { lock(); // Ensures that the lock will be released after `action` // is called, even if throws an exception. scope(exit) unlock(); action(); } } class Mutex : Lockable { void lock() { /* ... */ } void unlock() { /* ... */ } // Can't override `performLocked` differently } A common example is frameworks which provide customization points for applications through non-final interface functions, but overall take-over the application control flow: interface App { /// Main application loop final bool run() { init(); while(handleInput()) { update(); auto frame = render(); // implement somewhere else as a free function present(frame); } return true; } /// Initializes the application's resources on startup. void init(); /// Handles the input. /// Returns: /// false - if the app should be closed and true - otherwise. bool handleInput(); /// Updates the application state after handling input. void update(); /// Renders and the next frame into a buffer and /// returns a reference to it. Framerender(); } Other times, it's just for convenience in generic code: interface SceneDscNode { final T get(T)() const { static if (isBoolean!T) return getBool(); else static if (isIntegral!T) return getInt.to!T(); else static if (isFloatingPoint!T) return getFloat.to!T(); else static if (isSomeString!T) return getString.to!T(); else static assert(0, "Type not supported: " ~ T.stringof); } string getName() const; SceneDscNode getChild(string propertyName) const; SceneDscNode[] getChildren() const; protected: bool getBool() const; long getInt() const; double getFloat() const; string getString() const; } class JsonValueWrapper : SceneDscNode { string getName() const { /* ... */ } SceneDscNode getChild(string propertyName) const { /* ... */ } SceneDscNode[] getChildren() const { /* ... */ } protected { bool getBool() const { /* ... */ } long getInt() const { /* ... */ } double getFloat() const { /* ... */ } string getString() const { /* ... */ } } private JSONValue json; } class SdlValueWrapper : SceneDscNode { string getName() const { /* ... */ } SceneDscNode getChild(string propertyName) const { /* ... */ } SceneDscNode[] getChildren() const { /* ... */ } protected { bool getBool() const { /* ... */ } long getInt() const { /* ... */ } double getFloat() const { /* ... */ } string getString() const { /* ... */ } } private const SDLTag sdl; }
Mar 29 2017
parent reply abad <abad.flt gmail.com> writes:
On Wednesday, 29 March 2017 at 11:06:55 UTC, Petar Kirov 
[ZombineDev] wrote:
 On Wednesday, 29 March 2017 at 10:12:08 UTC, abad wrote:
 On Wednesday, 29 March 2017 at 10:08:02 UTC, abad wrote:
 Related question, it seems that final methods are allowed in 
 interfaces. Obviously you can't implement them anywhere, so 
 is this also on purpose and on what rationale? :)
So actually it's just a question of not catching this mistake early, because obviously compilation will fail when any class tries to implement the interface so the end result is ok. Maybe it _could_ just disallow final methods altogether to catch the errors earlier. But very minor detail overall.
The idea between `final` functions in interfaces is to provide a default non-overridable implementation. For example:
Yes, does make sense. I was looking this from Java 7 perspective where interfaces can't implement any methods.
Mar 29 2017
parent Mike Parker <aldacron gmail.com> writes:
On Wednesday, 29 March 2017 at 11:17:48 UTC, abad wrote:

 Yes, does make sense. I was looking this from Java 7 
 perspective where interfaces can't implement any methods.
D did not support them either for much of its history. IIRC, we got them at some point after Java did.
Mar 29 2017
prev sibling next sibling parent Jonathan M Davis via Digitalmars-d-learn writes:
On Wednesday, March 29, 2017 10:08:02 abad via Digitalmars-d-learn wrote:
 Related question, it seems that final methods are allowed in
 interfaces. Obviously you can't implement them anywhere, so is
 this also on purpose and on what rationale? :)
If the function is final, it can have an implementation. interface I { final bool foo() { return true; } } class C : I { } void main() { } - Jonathan M Davis
Mar 29 2017
prev sibling next sibling parent Jonathan M Davis via Digitalmars-d-learn writes:
On Wednesday, March 29, 2017 10:08:02 abad via Digitalmars-d-learn wrote:
 Related question, it seems that final methods are allowed in
 interfaces. Obviously you can't implement them anywhere, so is
 this also on purpose and on what rationale? :)
If the function is final, it can have an implementation. interface I { final bool foo() { return true; } } class C : I { } void main() { } - Jonathan M Davis
Mar 29 2017
prev sibling next sibling parent "H. S. Teoh via Digitalmars-d-learn" <digitalmars-d-learn puremagic.com> writes:
On Wed, Mar 29, 2017 at 11:24:04AM -0700, Jonathan M Davis via
Digitalmars-d-learn wrote:
 On Wednesday, March 29, 2017 10:08:02 abad via Digitalmars-d-learn wrote:
 Related question, it seems that final methods are allowed in
 interfaces. Obviously you can't implement them anywhere, so is
 this also on purpose and on what rationale? :)
If the function is final, it can have an implementation.
[...] If a function is final, it *must* have an implementation, since there can be no further overrides that would provide one in a derived type. The rationale for allowing final methods in an interface is to provide users of the interface with nice syntactic sugar, e.g., a set of methods that are commonly used together abstracted into a single final method, while requiring subclasses to only implement a smaller number of orthogonal methods that can be used to implement that method. T -- When solving a problem, take care that you do not become part of the problem.
Mar 29 2017
prev sibling parent bauss <jj_1337 live.dk> writes:
On Wednesday, 29 March 2017 at 10:08:02 UTC, abad wrote:
 Related question, it seems that final methods are allowed in 
 interfaces. Obviously you can't implement them anywhere, so is 
 this also on purpose and on what rationale? :)
That is not necessarily true. Final doesn't imply it can't be implemented. It implies that it cannot be override.
Mar 30 2017
prev sibling parent XavierAP <n3minis-git yahoo.es> writes:
On Wednesday, 29 March 2017 at 09:50:10 UTC, abad wrote:
 
 Is this on purpose and what's the rationale?
In Andrei's book, chapter 6.9.1 "the non virtual interface (NVI) idiom" answers your question. It cites this article by Herb Sutter as the originator of the idea: http://www.gotw.ca/publications/mill18.htm
Mar 29 2017