digitalmars.D.learn - Factory pattern in D
- Chris (22/22) May 01 2015 What would be the D equivalent of the factory pattern? This
- Namespace (16/16) May 01 2015 How about this:
- Namespace (7/23) May 01 2015 Of course, you can restrict the type to A or B, or both:
- Chris (5/21) May 01 2015 That's what I was looking for, I just couldn't get it right.
- biozic (24/49) May 01 2015 This might be a bit more useful:
- Chris (6/58) May 01 2015 Duh, I tried `static if` yesterday and I still got "Error:
- Chris (2/64) May 01 2015 And thanks, by the way!
- Chris (14/79) May 01 2015 Thinking about it,
- biozic (6/86) May 01 2015 But then I don't know what factory!X() provides that X() alone
- Chris (22/46) May 01 2015 Just cleaner code with type checks
- biozic (10/43) May 01 2015 A "factory" that produces a *type* could be:
- anonymous (5/13) May 01 2015 Obviously, myType's static type and factory's return type can't
- Rikki Cattermole (2/24) May 01 2015 Interfaces/classes not structs.
What would be the D equivalent of the factory pattern? This obviously doesn't work: struct A { int x = 42; } struct B { int x = 7; } auto factory(string type) { if (type == "A") return A(); else if (type == "B") return B(); else return A(); // default } void main() { auto a = factory("A"); } Error: mismatched function return type inference of B and A (dmd 2.067.1)
May 01 2015
How about this: ---- struct A { int x = 42; } struct B { int x = 7; } T factory(T)() { return T(); } void main() { auto a = factory!(A); } ----
May 01 2015
On Friday, 1 May 2015 at 10:04:46 UTC, Namespace wrote:How about this: ---- struct A { int x = 42; } struct B { int x = 7; } T factory(T)() { return T(); } void main() { auto a = factory!(A); } ----Of course, you can restrict the type to A or B, or both: ---- T factory(T)() if (is(T == A) || is(T == B)) { return T(); } ----
May 01 2015
On Friday, 1 May 2015 at 10:04:46 UTC, Namespace wrote:How about this: ---- struct A { int x = 42; } struct B { int x = 7; } T factory(T)() { return T(); } void main() { auto a = factory!(A); } ----That's what I was looking for, I just couldn't get it right. Thanks. Rikki: I wanted to avoid classes and interfaces.
May 01 2015
On Friday, 1 May 2015 at 10:12:36 UTC, Chris wrote:On Friday, 1 May 2015 at 10:04:46 UTC, Namespace wrote:This might be a bit more useful: --- struct A { int x = 42; } struct B { int x = 7; } auto factory(string type = "")() { static if (type == "A") return A(); else static if (type == "B") return B(); else return A(); // default } void main() { auto a = factory!"A"; auto b = factory!"B"; auto x = factory; } ---How about this: ---- struct A { int x = 42; } struct B { int x = 7; } T factory(T)() { return T(); } void main() { auto a = factory!(A); } ----That's what I was looking for, I just couldn't get it right. Thanks. Rikki: I wanted to avoid classes and interfaces.
May 01 2015
On Friday, 1 May 2015 at 10:27:16 UTC, biozic wrote:On Friday, 1 May 2015 at 10:12:36 UTC, Chris wrote:Duh, I tried `static if` yesterday and I still got "Error: mismatched function return type inference of B and A". Now it works! Sure, I must have overlooked something. Sometimes it's better to go home and call it a day than to try to get something to work.On Friday, 1 May 2015 at 10:04:46 UTC, Namespace wrote:This might be a bit more useful: --- struct A { int x = 42; } struct B { int x = 7; } auto factory(string type = "")() { static if (type == "A") return A(); else static if (type == "B") return B(); else return A(); // default } void main() { auto a = factory!"A"; auto b = factory!"B"; auto x = factory; } ---How about this: ---- struct A { int x = 42; } struct B { int x = 7; } T factory(T)() { return T(); } void main() { auto a = factory!(A); } ----That's what I was looking for, I just couldn't get it right. Thanks. Rikki: I wanted to avoid classes and interfaces.
May 01 2015
On Friday, 1 May 2015 at 10:46:20 UTC, Chris wrote:On Friday, 1 May 2015 at 10:27:16 UTC, biozic wrote:And thanks, by the way!On Friday, 1 May 2015 at 10:12:36 UTC, Chris wrote:Duh, I tried `static if` yesterday and I still got "Error: mismatched function return type inference of B and A". Now it works! Sure, I must have overlooked something. Sometimes it's better to go home and call it a day than to try to get something to work.On Friday, 1 May 2015 at 10:04:46 UTC, Namespace wrote:This might be a bit more useful: --- struct A { int x = 42; } struct B { int x = 7; } auto factory(string type = "")() { static if (type == "A") return A(); else static if (type == "B") return B(); else return A(); // default } void main() { auto a = factory!"A"; auto b = factory!"B"; auto x = factory; } ---How about this: ---- struct A { int x = 42; } struct B { int x = 7; } T factory(T)() { return T(); } void main() { auto a = factory!(A); } ----That's what I was looking for, I just couldn't get it right. Thanks. Rikki: I wanted to avoid classes and interfaces.
May 01 2015
On Friday, 1 May 2015 at 10:47:22 UTC, Chris wrote:On Friday, 1 May 2015 at 10:46:20 UTC, Chris wrote:Thinking about it, T factory(T)() { return T(); } is better suited for a factory (with static type checks). This aside, how would I get something to load dynamically? It's either "mismatched function return type" or (with type check) "variable X cannot be read at compile time": void main(string[] args) { auto type = args[1]; auto myType = factory!type(); } So it's back to classes/interfaces again? Hmmmm.On Friday, 1 May 2015 at 10:27:16 UTC, biozic wrote:And thanks, by the way!On Friday, 1 May 2015 at 10:12:36 UTC, Chris wrote:Duh, I tried `static if` yesterday and I still got "Error: mismatched function return type inference of B and A". Now it works! Sure, I must have overlooked something. Sometimes it's better to go home and call it a day than to try to get something to work.On Friday, 1 May 2015 at 10:04:46 UTC, Namespace wrote:This might be a bit more useful: --- struct A { int x = 42; } struct B { int x = 7; } auto factory(string type = "")() { static if (type == "A") return A(); else static if (type == "B") return B(); else return A(); // default } void main() { auto a = factory!"A"; auto b = factory!"B"; auto x = factory; } ---How about this: ---- struct A { int x = 42; } struct B { int x = 7; } T factory(T)() { return T(); } void main() { auto a = factory!(A); } ----That's what I was looking for, I just couldn't get it right. Thanks. Rikki: I wanted to avoid classes and interfaces.
May 01 2015
On Friday, 1 May 2015 at 11:01:29 UTC, Chris wrote:On Friday, 1 May 2015 at 10:47:22 UTC, Chris wrote:But then I don't know what factory!X() provides that X() alone doesn't.On Friday, 1 May 2015 at 10:46:20 UTC, Chris wrote:Thinking about it, T factory(T)() { return T(); } is better suited for a factory (with static type checks).On Friday, 1 May 2015 at 10:27:16 UTC, biozic wrote:And thanks, by the way!On Friday, 1 May 2015 at 10:12:36 UTC, Chris wrote:Duh, I tried `static if` yesterday and I still got "Error: mismatched function return type inference of B and A". Now it works! Sure, I must have overlooked something. Sometimes it's better to go home and call it a day than to try to get something to work.On Friday, 1 May 2015 at 10:04:46 UTC, Namespace wrote:This might be a bit more useful: --- struct A { int x = 42; } struct B { int x = 7; } auto factory(string type = "")() { static if (type == "A") return A(); else static if (type == "B") return B(); else return A(); // default } void main() { auto a = factory!"A"; auto b = factory!"B"; auto x = factory; } ---How about this: ---- struct A { int x = 42; } struct B { int x = 7; } T factory(T)() { return T(); } void main() { auto a = factory!(A); } ----That's what I was looking for, I just couldn't get it right. Thanks. Rikki: I wanted to avoid classes and interfaces.This aside, how would I get something to load dynamically? It's either "mismatched function return type" or (with type check) "variable X cannot be read at compile time": void main(string[] args) { auto type = args[1]; auto myType = factory!type(); } So it's back to classes/interfaces again? Hmmmm.Indeed. Runtime polymorphism is based on classes and interfaces. The struct and template solutions can only make "compile-time factories".
May 01 2015
On Friday, 1 May 2015 at 11:11:28 UTC, biozic wrote:On Friday, 1 May 2015 at 11:01:29 UTC, Chris wrote:Just cleaner code with type checks T factory(T)() { static if (is (T == A) || (is (T == B))) return T(); else assert(0, "Type "~T.stringof~" is not supported"); } and then you could have auto getType(string type = "")() { static if (type == "A") return factory!A(); else static if (type == "B") return factroy!B(); else return factory!A(); // default } in order to separate the logic, i.e. the factory produces the type and performs all the type checks, whereas `getType` is the interface for the user.Thinking about it, T factory(T)() { return T(); } is better suited for a factory (with static type checks).But then I don't know what factory!X() provides that X() alone doesn't.Yep. Only that "compile-time factories" kinda defeat the purpose.This aside, how would I get something to load dynamically? It's either "mismatched function return type" or (with type check) "variable X cannot be read at compile time": void main(string[] args) { auto type = args[1]; auto myType = factory!type(); } So it's back to classes/interfaces again? Hmmmm.Indeed. Runtime polymorphism is based on classes and interfaces. The struct and template solutions can only make "compile-time factories".
May 01 2015
On Friday, 1 May 2015 at 11:20:32 UTC, Chris wrote:On Friday, 1 May 2015 at 11:11:28 UTC, biozic wrote:A "factory" that produces a *type* could be: -- template checked(T) { static if (is (T == A) || (is (T == B))) alias checked = T; else static assert(0, "Type "~T.stringof~" is not supported"); } --On Friday, 1 May 2015 at 11:01:29 UTC, Chris wrote:Just cleaner code with type checks T factory(T)() { static if (is (T == A) || (is (T == B))) return T(); else assert(0, "Type "~T.stringof~" is not supported"); } and then you could have auto getType(string type = "")() { static if (type == "A") return factory!A(); else static if (type == "B") return factroy!B(); else return factory!A(); // default } in order to separate the logic, i.e. the factory produces the type and performs all the type checks, whereas `getType` is the interface for the user.Thinking about it, T factory(T)() { return T(); } is better suited for a factory (with static type checks).But then I don't know what factory!X() provides that X() alone doesn't.
May 01 2015
On Friday, 1 May 2015 at 11:01:29 UTC, Chris wrote:This aside, how would I get something to load dynamically? It's either "mismatched function return type" or (with type check) "variable X cannot be read at compile time": void main(string[] args) { auto type = args[1]; auto myType = factory!type(); } So it's back to classes/interfaces again? Hmmmm.Obviously, myType's static type and factory's return type can't depend on a dynamic value like args[1]. You could let factory return a std.variant.Variant, but at that point maybe just go with classes.
May 01 2015
On 1/05/2015 10:01 p.m., Chris wrote:What would be the D equivalent of the factory pattern? This obviously doesn't work: struct A { int x = 42; } struct B { int x = 7; } auto factory(string type) { if (type == "A") return A(); else if (type == "B") return B(); else return A(); // default } void main() { auto a = factory("A"); } Error: mismatched function return type inference of B and A (dmd 2.067.1)Interfaces/classes not structs.
May 01 2015