Private symbol (in)visibility within a module

NotYouAgain NotYouAgain at gmail.com
Sun May 5 07:22:32 UTC 2024


Specifying more than one function with the same name in the same 
scope is known as overloaded functions.

Overloaded functions enable you to supply different semantics for 
a function, depending on the types and number of its arguments.

In C++, C#, Java, Swift...and others, senseless name clashes do 
not occur between private and public symbols.

Only with D does the nature of a private symbol take on an 
**inconsistent** meaning.

Examples below (for comparison), include: C#, Java, Swift, C++ 
and D.

================ C# ====================
static int Main()
{
   Foo f = new Foo();
   Console.WriteLine(f.test(4)); // Error
   Console.WriteLine(f.test("hi there!"));
   return 0;
}

public class Foo
{
   private int test(int n) { return n; }
   public string test(string str) { return str; }
}

===== Java =============
public class Program
{
     public static void main(String[] args)
     {
         Foo f = new Foo();
         System.out.println(f.test(4)); // Error
         System.out.println(f.test("hi there!"));

     }
}

class Foo
{
     private int test(int n) { return n; }
     public String test(String str) { return str; }
}

========= Swift ===========
class Foo
{
     private func test(val: Int) -> Int
     {
         return val;
     }

     fileprivate func test(val: String) -> String
     {
         return val;
     }
}

var f = Foo();

print(f.test(val: 5));  // Error
print(f.test(val: "Hi there!"));

============  C ++  ======================

class Foo
{
     private: int test(int n) { return n; }
     public: std::string test(std::string str) { return str; }
};


int main()
{
     Foo f;

     std::cout << f.test(4) << '\n'; // Error
     std::cout << f.test("hi there!") << '\n';
     return 0;
}

============  D  is different to ***ALL*** of the above 
==============
module m;
@safe:
private:

import std;

void main()
{
     Foo f = new Foo();

     writeln(f.test(3)); // fine, calls the private method of a 
class
     writeln(f.test("hi there!")); // fine, calls the public 
method of a class
}

public class Foo
{
     private int test(int n) { return n; }
     public string test(string str) { return str; }
}
=================================

So why is D different here? Because the lowest level of 
modularity in D is 'the module', and classes/structs within a 
module have no mechanism in D to explicately encapsulate 
themselves. Their encapsulation is wholly dependent on the 
encapsulation at the module level.

I propose D introduce some CONSISTENCY with the concept of 
'private', by allowing classes/struct to once again have their 
OWN private members through the use of a new attribute 
'private(this)', and requiring that D exclude private(this) 
members from the overload lookup set as well.

Thus, with such a change:
=============================
module m;
@safe:
private:

import std;

void main()
{
     Foo f = new Foo();

     writeln(f.test(3)); // Error
     writeln(f.test("hi there!"));
}

public class Foo
{
     private(this) int test(int n) { return n; }
     public string test(string str) { return str; }
}
=====================================

Some background:

https://wiki.dlang.org/DIP22
https://forum.dlang.org/post/kb33b3$2346$1@digitalmars.com





More information about the dip.ideas mailing list