June 14, 2022
On Tuesday, 14 June 2022 at 12:19:40 UTC, Mike Parker wrote:
> On Tuesday, 14 June 2022 at 10:50:56 UTC, bauss wrote:
>
>> No you really can't and I already proved that with a couple examples in the other discussions on this topic; there are situations where you cannot do that, such as accessing private fields on a parent class using a sub class type within the parent class' module.
>
> And Paul did show you how to do that with `child.Foo._c`.

Which is a pointless thing to say, you are still violating the subtyping relationship.
June 14, 2022

On Tuesday, 14 June 2022 at 12:28:24 UTC, Ola Fosheim Grøstad wrote:

>

On Tuesday, 14 June 2022 at 12:19:40 UTC, Mike Parker wrote:\

>

And Paul did show you how to do that with child.Foo._c.

Which is a pointless thing to say, you are still violating the subtyping relationship.

So then what do you do when your direct access to child._c suddenly starts causing a subtle bug because someone added later added a _c member to the public interface of Bar? Private members are not inherited and do not impact the public interface.

June 14, 2022
On Tuesday, 14 June 2022 at 12:19:40 UTC, Mike Parker wrote:
> On Tuesday, 14 June 2022 at 10:50:56 UTC, bauss wrote:
>
>> No you really can't and I already proved that with a couple examples in the other discussions on this topic; there are situations where you cannot do that, such as accessing private fields on a parent class using a sub class type within the parent class' module.
>
> And Paul did show you how to do that with `child.Foo._c`.

Not in a legal way.
June 14, 2022
On Tuesday, 14 June 2022 at 12:35:24 UTC, bauss wrote:
> On Tuesday, 14 June 2022 at 12:19:40 UTC, Mike Parker wrote:
>> And Paul did show you how to do that with `child.Foo._c`.
>
> Not in a legal way.

What do you mean?
June 14, 2022

On Tuesday, 14 June 2022 at 12:33:53 UTC, Mike Parker wrote:

>

On Tuesday, 14 June 2022 at 12:28:24 UTC, Ola Fosheim Grøstad wrote:

>

On Tuesday, 14 June 2022 at 12:19:40 UTC, Mike Parker wrote:\

>

And Paul did show you how to do that with child.Foo._c.

Which is a pointless thing to say, you are still violating the subtyping relationship.

So then what do you do when your direct access to child._c suddenly starts causing a subtle bug because someone added later added a _c member to the public interface of Bar? Private members are not inherited and do not impact the public interface.

You get an error, just like in C++!

Then you disambiguate.

(Private members are inherited 100%.)

June 14, 2022

On Tuesday, 14 June 2022 at 12:33:53 UTC, Mike Parker wrote:

>

So then what do you do when your direct access to child._c suddenly starts causing a subtle bug because someone added later added a _c member to the public interface of Bar? Private members are not inherited and do not impact the public interface.

That shouldn't matter, if you have access to screw up with _c, then you have access to the module and thus it is your own responsibility to make sure you don't create subtle bugs.

Isn't that the whole point behind module-level privacy?

You have access to the module, thus you have control over the module. It shouldn't matter how you get into the module etc. since you're the owner of the module, then you're the one responsible for it.

You see, your argument against all of this is the exact argument that is for type-level privacy, since you wouldn't be able to create a subtle bug like this and you wouldn't be able to cast to the parent type in the module and hack your way around that way either.

It solves both problems.

June 14, 2022
On Tuesday, 14 June 2022 at 12:09:57 UTC, bauss wrote:
> On Tuesday, 14 June 2022 at 11:04:55 UTC, The Zealot wrote:
>> On Tuesday, 14 June 2022 at 10:50:56 UTC, bauss wrote:
>>> On Tuesday, 14 June 2022 at 10:21:34 UTC, The Zealot wrote:
>>>>
>>>> a) put the class in it's own module.
>>>>
>>>
>>> No you really can't and I already proved that with a couple examples in the other discussions on this topic; there are situations where you cannot do that, such as accessing private fields on a parent class using a sub class type within the parent class' module.
>>>
>>> That's why the module-level private is a lie in D or at least incomplete.
>>
>> The code you posted works exactly as it should. your function void handle(Bar child) does access the class Bar of another module, and the members of foo are not accessible.
>> and you can implement the desired behaviour like this:
>>
>> import b;
>> void handle(Bar child) if(isDerivedFrom!(Foo, Bar))
>> {
>>   (cast(Foo)child)._c += child.c;
>> }
>
> No it does not. You should never have to cast to a parent type, NEVER!
>
> That is a red flag if you have to do that, a major one at that.

no this is actually perfectly fine, as the code ensures at compiletime that Bar is in fact a subtype of Foo, so the cast is always valid. You have to be explicit that you actually want to use Foo's _c; or else adding a _c variable to Bar silently changes the behaviour of your code. This works as intended.
June 14, 2022

On Tuesday, 14 June 2022 at 12:39:33 UTC, bauss wrote:

>

That shouldn't matter, if you have access to screw up with _c, then you have access to the module and thus it is your own responsibility to make sure you don't create subtle bugs.

Isn't that the whole point behind module-level privacy?

You have access to the module, thus you have control over the module. It shouldn't matter how you get into the module etc. since you're the owner of the module, then you're the one responsible for it.

You see, your argument against all of this is the exact argument that is for type-level privacy, since you wouldn't be able to create a subtle bug like this and you wouldn't be able to cast to the parent type in the module and hack your way around that way either.

It solves both problems.

No, that doesn't hold in your example because Bar was not in the same module. Going through .Foo gives you access to Foo's private parts because it is in the same module.

If you want to argue that you should be able to access child._c when both Bar and Foo are in the same module, well, you can:

class Foo {
    private int _c;
}

class Bar : Foo {
}

void baz(Bar child) {
    child._c = 10;
}

void main()
{
    Bar b = new Bar;
    baz(b);
    writeln(b._c);
}
June 14, 2022

On Tuesday, 14 June 2022 at 12:47:31 UTC, Mike Parker wrote:

>

On Tuesday, 14 June 2022 at 12:39:33 UTC, bauss wrote:

>

That shouldn't matter, if you have access to screw up with _c, then you have access to the module and thus it is your own responsibility to make sure you don't create subtle bugs.

Isn't that the whole point behind module-level privacy?

You have access to the module, thus you have control over the module. It shouldn't matter how you get into the module etc. since you're the owner of the module, then you're the one responsible for it.

You see, your argument against all of this is the exact argument that is for type-level privacy, since you wouldn't be able to create a subtle bug like this and you wouldn't be able to cast to the parent type in the module and hack your way around that way either.

It solves both problems.

No, that doesn't hold in your example because Bar was not in the same module. Going through .Foo gives you access to Foo's private parts because it is in the same module.

If you want to argue that you should be able to access child._c when both Bar and Foo are in the same module, well, you can:

class Foo {
    private int _c;
}

class Bar : Foo {
}

void baz(Bar child) {
    child._c = 10;
}

void main()
{
    Bar b = new Bar;
    baz(b);
    writeln(b._c);
}

Sure Bar wasn't in the same module, but Foo is and Bar inherits from Foo, thus Bar is Foo and Foo has access to _c in Foo's module and thus Bar should have access to Foo's private members in Foo's module, because Bar is Foo.

It's really not that difficult to grasp such a concept.

Here it is illustrated with my terrible graphic skills:

https://i.postimg.cc/0Q3XSN47/illustrated.png

June 14, 2022
>>> import b;
>>> void handle(Bar child) if(isDerivedFrom!(Foo, Bar))
>>> {
>>>   (cast(Foo)child)._c += child.c;
>>> }
>>
>> No it does not. You should never have to cast to a parent type, NEVER!
>>
>> That is a red flag if you have to do that, a major one at that.
>
> no this is actually perfectly fine, as the code ensures at compiletime that Bar is in fact a subtype of Foo, so the cast is always valid. You have to be explicit that you actually want to use Foo's _c; or else adding a _c variable to Bar silently changes the behaviour of your code. This works as intended.

and just to be clear, you don't even need to do it with an explicit cast.
All you have to do is access _c through a baseclass pointer.