April 08, 2018
On 08.04.2018 16:36, Timon Gehr wrote:
> On 08.04.2018 15:00, bauss wrote:
>>
>> It's perfectly normal in other languages that supports classes to access private members of parent's as long as you're within the parent's encapsulation.
> 
> That is not true. Use 'protected'.

Actually, I misunderstood your sentence.
This is definitely a bug.
April 08, 2018
On Saturday, 7 April 2018 at 20:14:49 UTC, bauss wrote:
> jesus that became a long title.
>
> Anyway as the title says, is it a bug that a parent class that access its own private members from derived classes gets deprecation warning?
>
> Scenario narrowed down:
>
> // module foo;
> class Foo
> {
>     private:
>     bool _baz;
>
>     public:
>     final void foos(T : Foo)(string key, T[] values)
>     {
>       if (values && values.length)
>       {
>         foreach (child; values)
>         {
>           child._isChild = true;
>         }
>       }
>     }
> }
>
> // module bar;
> class Bar : Foo
> {
> }
>
> The above in my case will give a deprecation warning that "_baz" isn't visible from "Bar".

Well, template has nothing to do with it. Also, private members in D are private to the module, not to the class. Here's a reduced example:

--- foo.d ---
import bar;

class Foo
{
    private bool baz;
}

void test(Bar b)
{
    b.baz = true;
}

--- bar.d ---
import foo;

class Bar : Foo {}

void main()
{
    test(new Bar);
}

https://wiki.dlang.org/DIP22 mentions something called "look-up origin"; the meaning of that term is unclear to me...

April 08, 2018
On Sunday, 8 April 2018 at 14:45:34 UTC, kdevel wrote:
> On Sunday, 8 April 2018 at 13:00:02 UTC, bauss wrote:
>
> [...]
>
>> // a.d
>> module a;
>>
>> class Foo
>> {
>> 	private:
>> 	bool _baz;
>> 	
>> 	public:
>> 	void handleBar(T : Foo)(T[] foos)
>> 	{
>> 		foreach (child; foos)
>> 		{
>> 			child._baz = true; // Not ok.
>
> replace this line with
>
>    import std.stdio;
>    __PRETTY_FUNCTION__.writeln;
>    foos.writeln;
>
> This writelns:
>
>    void a.Foo.handleBar!(Bar).handleBar(Bar[] foos)
>    [b.Bar, b.Bar]
>
> So foos is actually an array of Bars. And there is no access from a Bar to the private elements of it's baseclass Foo.

Yes, but we're in the module a and private is module level, so it should be accessible from the function regardless of whether it's Bar or not.

April 09, 2018
On Sunday, 8 April 2018 at 13:00:02 UTC, bauss wrote:
> I think it's better demonstrated like this, because to me the behavior makes no sense.
>
> Especially since you can just cast "Bar" to "Foo" and then you're allowed to do it.
>
> Since we're inside Foo then it shouldn't care whether "_baz" is private or not.
>
> I could understand if the function was located within Bar, but it's not.
>
> It's perfectly normal in other languages that supports classes to access private members of parent's as long as you're within the parent's encapsulation.
>
> // a.d
> module a;
>
> class Foo
> {
> 	private:
> 	bool _baz;
> 	
> 	public:
> 	void handleBar(T : Foo)(T[] foos)
> 	{
> 		foreach (child; foos)
> 		{
> 			child._baz = true; // Not ok.
> 			(cast(Foo)child)._baz = true; // Ok.
> 		}
> 	}
> }
>
> // b.d
> module b;
>
> import a;
>
> class Bar : Foo
> {
> 	
> }
>
> // main.d
>
> module main;
>
> import b;
>
> void main()
> {
> 	auto bars = [new Bar, new Bar];
> 	auto bar = new Bar;
> 	bar.handleBar(bars);
> }

Actually, this behaves as i would expect.
`_baz` is a private member of Foo (to be precise: it belongs to module `a`)
in handleBar(), you iterate `Bar[]` - which is in module `b`.
By casting it to Foo, you are accessing the wanted module (`a`) again.

April 09, 2018
On Monday, 9 April 2018 at 17:05:45 UTC, martin wrote:
> On Sunday, 8 April 2018 at 13:00:02 UTC, bauss wrote:
>> I think it's better demonstrated like this, because to me the behavior makes no sense.
>>
>> Especially since you can just cast "Bar" to "Foo" and then you're allowed to do it.
>>
>> Since we're inside Foo then it shouldn't care whether "_baz" is private or not.
>>
>> I could understand if the function was located within Bar, but it's not.
>>
>> It's perfectly normal in other languages that supports classes to access private members of parent's as long as you're within the parent's encapsulation.
>>
>> // a.d
>> module a;
>>
>> class Foo
>> {
>> 	private:
>> 	bool _baz;
>> 	
>> 	public:
>> 	void handleBar(T : Foo)(T[] foos)
>> 	{
>> 		foreach (child; foos)
>> 		{
>> 			child._baz = true; // Not ok.
>> 			(cast(Foo)child)._baz = true; // Ok.
>> 		}
>> 	}
>> }
>>
>> // b.d
>> module b;
>>
>> import a;
>>
>> class Bar : Foo
>> {
>> 	
>> }
>>
>> // main.d
>>
>> module main;
>>
>> import b;
>>
>> void main()
>> {
>> 	auto bars = [new Bar, new Bar];
>> 	auto bar = new Bar;
>> 	bar.handleBar(bars);
>> }
>
> Actually, this behaves as i would expect.
> `_baz` is a private member of Foo (to be precise: it belongs to module `a`)
> in handleBar(), you iterate `Bar[]` - which is in module `b`.
> By casting it to Foo, you are accessing the wanted module (`a`) again.

but handleBar() is in a.

This behavior is allowed in ex. C#
April 11, 2018
On Monday, 9 April 2018 at 17:16:56 UTC, bauss wrote:
> On Monday, 9 April 2018 at 17:05:45 UTC, martin wrote:>>
>> Actually, this behaves as i would expect.
>> `_baz` is a private member of Foo (to be precise: it belongs to module `a`)
>> in handleBar(), you iterate `Bar[]` - which is in module `b`.
>> By casting it to Foo, you are accessing the wanted module (`a`) again.
>
> but handleBar() is in a.
>
> This behavior is allowed in ex. C#

`_baz` is a member of `module a : Foo` - `_baz`, as is `handleBar()`.
`protected` is the Access specifier you want.
If i understand you correctly, you want it to behave as  if `_baz` would be a member of `handleBar()`

If this is really possible in C#, it lets my eyebrow raise.

April 11, 2018
On Wednesday, 11 April 2018 at 17:20:23 UTC, martin wrote:
> On Monday, 9 April 2018 at 17:16:56 UTC, bauss wrote:
>> On Monday, 9 April 2018 at 17:05:45 UTC, martin wrote:>>
>>> Actually, this behaves as i would expect.
>>> `_baz` is a private member of Foo (to be precise: it belongs to module `a`)
>>> in handleBar(), you iterate `Bar[]` - which is in module `b`.
>>> By casting it to Foo, you are accessing the wanted module (`a`) again.
>>
>> but handleBar() is in a.
>>
>> This behavior is allowed in ex. C#
>
> `_baz` is a member of `module a : Foo` - `_baz`, as is `handleBar()`.
> `protected` is the Access specifier you want.
> If i understand you correctly, you want it to behave as  if `_baz` would be a member of `handleBar()`
>
> If this is really possible in C#, it lets my eyebrow raise.

Execute the following C# program and it will work just fine:

It's a really common pattern with OOP.

public class Foo
{
	private string _baz;
	
	public void HandleBar(Bar bar)
	{
		bar._baz = "Hello";
	}
}

public class Bar : Foo
{
}

...

var bar = new Bar();
bar.HandleBar(bar);
April 11, 2018
On Wednesday, 11 April 2018 at 17:34:40 UTC, bauss wrote:
> On Wednesday, 11 April 2018 at 17:20:23 UTC, martin wrote:
>> On Monday, 9 April 2018 at 17:16:56 UTC, bauss wrote:
>>> On Monday, 9 April 2018 at 17:05:45 UTC, martin wrote:>>
>>>> Actually, this behaves as i would expect.
>>>> `_baz` is a private member of Foo (to be precise: it belongs to module `a`)
>>>> in handleBar(), you iterate `Bar[]` - which is in module `b`.
>>>> By casting it to Foo, you are accessing the wanted module (`a`) again.
>>>
>>> but handleBar() is in a.
>>>
>>> This behavior is allowed in ex. C#
>>
>> `_baz` is a member of `module a : Foo` - `_baz`, as is `handleBar()`.
>> `protected` is the Access specifier you want.
>> If i understand you correctly, you want it to behave as  if `_baz` would be a member of `handleBar()`
>>
>> If this is really possible in C#, it lets my eyebrow raise.
>
> Execute the following C# program and it will work just fine:
>
> It's a really common pattern with OOP.
>
> public class Foo
> {
> 	private string _baz;
> 	
> 	public void HandleBar(Bar bar)
> 	{
> 		bar._baz = "Hello";
> 	}
> }
>
> public class Bar : Foo
> {
> }
>
> ...
>
> var bar = new Bar();
> bar.HandleBar(bar);

Also protected is not the access modifier I want.

I only want to set it through the parent class and it should only be used within the parent class.

But it's on each child passed to the parent class that it's set.

The children should NEVER touch the variable.
April 11, 2018
On Sunday, April 08, 2018 13:00:02 bauss via Digitalmars-d wrote:
> On Sunday, 8 April 2018 at 10:48:19 UTC, user1234 wrote:
> > On Saturday, 7 April 2018 at 20:46:39 UTC, bauss wrote:
> >> On Saturday, 7 April 2018 at 20:34:57 UTC, user1234 wrote:
> >>> On Saturday, 7 April 2018 at 20:14:49 UTC, bauss wrote:
> >>>> jesus that became a long title.
> >>>>
> >>>> Anyway as the title says, is it a bug that a parent class that access its own private members from derived classes gets deprecation warning?
> >>>
> >>> If the import is selective no. (`import foo : Foo;`)
> >>> If the import is for the whole module i'd say yes. (`import
> >>> foo;`)
> >>
> >> What do you mean?
> >>
> >> The problem is that "Foo" cannot access "_baz" without deperecation warning, but "_baz" is a part of "Foo".
> >
> > _baz is private and not protected. The deprecation was introduced because bug 314 broke the private protection.
>
> I think it's better demonstrated like this, because to me the behavior makes no sense.
>
> Especially since you can just cast "Bar" to "Foo" and then you're allowed to do it.
>
> Since we're inside Foo then it shouldn't care whether "_baz" is private or not.
>
> I could understand if the function was located within Bar, but it's not.
>
> It's perfectly normal in other languages that supports classes to access private members of parent's as long as you're within the parent's encapsulation.
>
> // a.d
> module a;
>
> class Foo
> {
>   private:
>   bool _baz;
>
>   public:
>   void handleBar(T : Foo)(T[] foos)
>   {
>       foreach (child; foos)
>       {
>           child._baz = true; // Not ok.
>           (cast(Foo)child)._baz = true; // Ok.
>       }
>   }
> }
>
> // b.d
> module b;
>
> import a;
>
> class Bar : Foo
> {
>
> }
>
> // main.d
>
> module main;
>
> import b;
>
> void main()
> {
>   auto bars = [new Bar, new Bar];
>   auto bar = new Bar;
>   bar.handleBar(bars);
> }

I don't know. It could be argued either way. I think that the logic as to why

child._baz = true;

is not legal is because you're accessing it through a class reference that does not have access to _baz, since it's private to the base class. Allowing access to the base class member via a derived class reference arguably violates private.

On the other hand, this is inside a member function of the base class, and the base class has access to the private members - even if they're in an object other than the current one. And by that logic, it should be legal to access the base class member even though it's through a derived class reference.

Usually, base classes don't handle any references for derived classes (they may handle derived classes through base class references but not usually through actual derived class references), and this sort of thing doesn't come up. As such, I think that the obvious result would be the current behavior regardless of whether that is actually the best behavior.

I suspect that this particular situation was never really thought through in the implementation, but I don't know. And since I think that there are good arguments in both directions, I really don't know whether the current implementation is better or whether what you're trying to do should be legal. Certainly, it seems like a valid enhancement request, though I have no idea whether Walter would think that what you're trying to do should work or not. I wouldn't be surprised either way.

- Jonathan M Davis

April 11, 2018
On 11.04.2018 19:58, Jonathan M Davis wrote:
> I don't know. It could be argued either way.

Not really. bauss is right about this.
https://en.wikipedia.org/wiki/Liskov_substitution_principle