Thread overview
How to allow +=, -=, etc operators and keep encapsulation?
Apr 12, 2021
Jack
Apr 13, 2021
evilrat
April 12, 2021

Give this class:

class A
{
	int X() { return x; }
	int X(int v) { return x = v;}

	private int x;
}

I'd like to allow use +=, -= operators on X() and keep encapsulation. What's a somehow elegant way to do that?

April 13, 2021

On Monday, 12 April 2021 at 18:16:14 UTC, Jack wrote:

>

Give this class:

class A
{
	int X() { return x; }
	int X(int v) { return x = v;}

	private int x;
}

I'd like to allow use +=, -= operators on X() and keep encapsulation. What's a somehow elegant way to do that?

I assume you know what you are doing, right?
In this specific case I would say you can probably stick with it as is since you can have value checks in getter/setter, you can validate and correct values before it mess up the internal state, and calculate X without exposing internal state (today it may be int x, tomorrow you change it to be stored as string, who knows...).

But this example doesn't really tell if it's acceptable in what you are trying to achieve.

Otherwise:

What you need is called abstraction, you provide high level interface to your problem without exposing internal state which is implementation detail, which gives you freedom to modify internal logic without breaking everyone's code that consume your interface.

Assuming A is some special scalar type you just implement all operations in a way that makes it only relevant as a whole. Otherwise if you still need to peek on its private members you have leaky abstractions (it is called feature envy).

April 13, 2021
On 4/12/21 2:16 PM, Jack wrote:
> Give this class:
> 
> ```d
> class A
> {
>      int X() { return x; }
>      int X(int v) { return x = v;}
> 
>      private int x;
> }
> ```
> 
> I'd like to allow use ```+=```, ```-=``` operators on ```X()``` and keep encapsulation. What's a somehow elegant way to do that?

It's really hard to do.

One problem is lifetime management. There is no way to do something like `ref`, which does not provide a way to make a copy of the original thing (the reference) in @safe code.

But the way I'd tackle it is to write a pseudo-reference wrapper that forwards to the getter/setter.

I'm sure there's a mixin template solution that works, I just don't have the time to code it out right now.

You can take a look at Mike Franklin's unpublished DIP here for inspiration:
* [DIP conversation](https://github.com/dlang/DIPs/pull/97)
* [DIP text](https://github.com/dlang/DIPs/blob/fdd016a16bf1898fda901b9d716f5bcc6021c1a7/DIPs/DIP1xxx-mvf.md)

-Steve