Thread overview
How to disable/hide constructor when using factory method?
Jan 23, 2019
JN
Jan 23, 2019
Alex
Jan 24, 2019
JN
Jan 24, 2019
Arafel
Jan 24, 2019
JN
Jan 24, 2019
Mike Parker
January 23, 2019
class Foo
{
    static Foo makeFoo()
    {
        Foo f = new Foo();
        return f;
    }
}

void main() {
    Foo f = Foo.makeFoo();
}

For a code like this. I'd like all users of the class to be forced to create instances using the static method makeFoo. I want to disallow "new Foo()". But I don't know if it's possible to disable the constructor, while still making it available in the makeFoo static method.

@disable this doesn't work, private this(); doesn't work either.
January 23, 2019
On Wednesday, 23 January 2019 at 19:26:37 UTC, JN wrote:
> class Foo
> {
>     static Foo makeFoo()
>     {
>         Foo f = new Foo();
>         return f;
>     }
> }
>
> void main() {
>     Foo f = Foo.makeFoo();
> }
>
> For a code like this. I'd like all users of the class to be forced to create instances using the static method makeFoo. I want to disallow "new Foo()". But I don't know if it's possible to disable the constructor, while still making it available in the makeFoo static method.
>
> @disable this doesn't work, private this(); doesn't work either.

private should work, if the class and the main are in different modules, no?
January 24, 2019
On Wednesday, 23 January 2019 at 19:41:44 UTC, Alex wrote:
> On Wednesday, 23 January 2019 at 19:26:37 UTC, JN wrote:
>> class Foo
>> {
>>     static Foo makeFoo()
>>     {
>>         Foo f = new Foo();
>>         return f;
>>     }
>> }
>>
>> void main() {
>>     Foo f = Foo.makeFoo();
>> }
>>
>> For a code like this. I'd like all users of the class to be forced to create instances using the static method makeFoo. I want to disallow "new Foo()". But I don't know if it's possible to disable the constructor, while still making it available in the makeFoo static method.
>>
>> @disable this doesn't work, private this(); doesn't work either.
>
> private should work, if the class and the main are in different modules, no?

I expected that too, but it doesn't even work in the same module.

class Foo
{
    private this();

    static Foo makeFoo()
    {
        Foo f = new Foo();
        return f;
    }
}

void main() {
}

fails with:

onlineapp.o:onlineapp.d:_D9onlineapp3Foo7__ClassZ: error: undefined reference to '_D9onlineapp3Foo6__ctorMFZCQzQr'
onlineapp.d:7: error: undefined reference to '_D9onlineapp3Foo6__ctorMFZCQzQr'
collect2: error: ld returned 1 exit status
Error: linker exited with status 1

I don't understand why is this a linker problem. My understanding is that for some reason static methods don't have access to the private constructor (they're not considered same module?). But even though, it should error with something like "Foo.makeFoo() cannot access private Foo.this()" rather than fail at linking.
January 24, 2019
You are declaring the constructor, but not defining it, i.e. you're telling the compiler that it's in some other compilation unit.

The compiler won't complain, but the linker will.

If you replace:

> private this();

with:

> private this() {}

it should work.

A.

On 1/24/19 1:48 PM, JN wrote:
> 
> I expected that too, but it doesn't even work in the same module.
> 
> class Foo
> {
>      private this();
> 
>      static Foo makeFoo()
>      {
>          Foo f = new Foo();
>          return f;
>      }
> }
> 
> void main() {
> }
> 
> fails with:
> 
> onlineapp.o:onlineapp.d:_D9onlineapp3Foo7__ClassZ: error: undefined reference to '_D9onlineapp3Foo6__ctorMFZCQzQr'
> onlineapp.d:7: error: undefined reference to '_D9onlineapp3Foo6__ctorMFZCQzQr'
> collect2: error: ld returned 1 exit status
> Error: linker exited with status 1
> 
> I don't understand why is this a linker problem. My understanding is that for some reason static methods don't have access to the private constructor (they're not considered same module?). But even though, it should error with something like "Foo.makeFoo() cannot access private Foo.this()" rather than fail at linking.

January 24, 2019
On Thursday, 24 January 2019 at 12:52:47 UTC, Arafel wrote:
> You are declaring the constructor, but not defining it, i.e. you're telling the compiler that it's in some other compilation unit.
>
> The compiler won't complain, but the linker will.
>
> If you replace:
>
>> [...]
>
> with:
>
>> [...]
>
> it should work.
>
> A.
>
> On 1/24/19 1:48 PM, JN wrote:
>> [...]

Doh. Of course. I feel so dumb. I just had it at @disable this();, then replaced @disable with private without thinking to add {}
January 24, 2019
On Thursday, 24 January 2019 at 12:58:15 UTC, JN wrote:

>
> Doh. Of course. I feel so dumb. I just had it at @disable this();, then replaced @disable with private without thinking to add {}

Give me a nickel for every time I've made an edit like that...!