www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - How to disable/hide constructor when using factory method?

reply JN <666total wp.pl> writes:
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.
Jan 23
parent reply Alex <sascha.orlov gmail.com> writes:
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?
Jan 23
parent reply JN <666total wp.pl> writes:
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.
Jan 24
parent reply Arafel <er.krali gmail.com> writes:
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.
Jan 24
parent reply JN <666total wp.pl> writes:
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 {}
Jan 24
parent Mike Parker <aldacron gmail.com> writes:
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...!
Jan 24