0

I have two abstract products types:

type abstractProductA = {.
  methodA: string
};

type abstractProductB = {.
  methodB: int
};

Used to create the following product classes:

class productA1 = {
  pub methodA => "This is methodA of ProductA1";
};

class productB1 = {
  pub methodB => 1;
};

I would like to call the instance of abstractProductA, as well as abstractProductB in my abstract factory. Something like the following(syntax is off, I know):

type abstractFactory = {.
  createProductA: abstractProductA,
  createProductB: abstractProductB
};

So that when I create new concreteFactory using the following class:

class concreteFactory1 = {
  pub createProductA => (new productA1);
  pub createProductB => (new productA1);
};

and constructer:

let g = new concreteFactory1#createProductB;
Js.log (g#methodA);

the compiler should complain that createProductB only takes an int, and not an string(which it currently does not).

Thank you, and any suggestions are more than welcome.

Charlie-Greenman
  • 1,469
  • 1
  • 16
  • 36
  • 1
    I don't understand your question. If you have two methods with different names, the compiler will check the names and complain about that before it checks the types. If it didn't, what types would it check against? – glennsl Oct 03 '17 at 21:19
  • glennsl I really appreciate your help on this and others. Going to look into again momentarily and report back. – Charlie-Greenman Oct 03 '17 at 21:33
  • @glennsl Question updated. As you can see the createProductB method for the concreteFactory1 is using a string, but following the abstractFactory, type, ideally compiler should error out, createProductB can only return an int, and not a string. That would be what I am trying to achieve. Thank you for your patience. – Charlie-Greenman Oct 04 '17 at 12:53
  • 1
    Sorry, I still don't understand. `abstractProductB` doesn't have a `methodA`, so it'll complain about that before checking the method's type, since if there's no method, there's no method type to check either. But even if it did, `Js.log` accepts anything (its type is `'a => unit`. If you want the compiler to complain about it not being a string, you need to use it with something that is restricted to strings. – glennsl Oct 04 '17 at 13:06
  • From what I understand, the compiler is not complaining about it: https://reasonml.github.io/try/?reason=C4TwDgpgBAhgRgZ2AJxgY2ABWQewCYCuGAglALxQDeAdAFBRQC2EwAFvsQFxRLICWAOwDmtAL4BuWrVCRYiFOiy5CGAELkqdBszb5V3QcDGTp4aPF6KAYopzIQGmvShpkEGMAjZ8RYFzmWGN4qfgA0zq7unsG++gEKQcqxxlJoADYwCAhQYEkkAIyOzmAEcEws7HikZAB8UABEACqsfNmt5bpVUDgAZlAxBfWSEqkZWTl5wKqFFJTFpR2V6rVQ+cMm6ZnZaDgCkZ42GHYgM1TzZZEeXpPVdQAUAhAA7hM+avkAlJIMJRduVwMpuR7o8Xrk3lNPuspGkWFAhBpQS5dvsIIdgMd8gBiS7RG6SABSCGoaRwCLuQixOiWHyAA – Charlie-Greenman Oct 04 '17 at 13:08
  • 1
    Well, you return a `productB` from `createProductA` which does have a `methodB`. If you try `#methodA` you'll get an error. – glennsl Oct 04 '17 at 13:51
  • 1
    It seems like perhaps you assume `concreteFactory1` will automatically conform to `abstractFactory`, but then you'd get an error much earlier. – glennsl Oct 04 '17 at 13:53
  • @glennsl that would be what I am trying to do. I am trying to get concreteFactory1 to automatically conform to abstractFactory – Charlie-Greenman Oct 04 '17 at 13:56
  • In addition, that would be the question I am trying to ask. – Charlie-Greenman Oct 04 '17 at 13:56
  • 1
    Right, then you have to use a virtual class instead. Like this: https://reasonml.github.io/try/?reason=C4TwDgpgBAhgRgZ2AJxgY2ABWQewCYCuGAglALxQDeAdAFBRQC2EwAFvsQFxRLICWAOwDmtAL4BuWrVCRYiFOiy5CGAELkqdBszb5V3QcDGTaaADYwECKADc+yYARhm5vRQDFFOZCA2V6UGAEcLb2js5QaMgQMMAQ2PhEwFyuChgJKsmSDEEhdg5OLlExcRlJ+qmo6crlkhJS5pbWYDUkAIx+AblMLOx4pGQAfFAARAAqrHzWUz26-VA4AGZQZe0jdSaNVoGtwKodFP45wbN96kNQbRsNFttoOALFcZ4Y3iAHVAGCrBD8wJUeLw+bKBE7FWLxXYDYYACgEEAA7jtEmo2gBKEHdcGlXbnWHwpEtFF7dHXWhmFhQIQaAmRB5PCAvYBvNoAYmxkOJxEkACkENQzDhqTChKydH1iGigA – glennsl Oct 04 '17 at 14:01
  • Terrific, that would be it. Feel free to answer. Will accept and upvote. – Charlie-Greenman Oct 04 '17 at 14:03
  • 1
    Cool. I think the question could use some clarification as well though, if you're able. It's still not clear to me what you're asking without reading the comments. – glennsl Oct 04 '17 at 14:06
  • 1
    Ok, will modify question in about 2-3 hours. – Charlie-Greenman Oct 04 '17 at 14:06
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/155953/discussion-between-master-chief-and-glennsl). – Charlie-Greenman Oct 04 '17 at 17:30

1 Answers1

1

It seems the error should occur where createProductB returns productA1 instead of productB1. In order to achieve that, you'll need to define a virtual class for abstractFactory instead of just an object type, and then have concreteFactory explicitly inherit from it.

class virtual abstractFactory = {
  pub virtual createProductA: abstractProductA;
  pub virtual createProductB: abstractProductB;
};

class concreteFactory1 = {
  inherit abstractFactory;
  pub createProductA => (new productB1);
  pub createProductB => (new productB1);
};

This will produce the following error on pub createProductA => (new productB1):

This expression has type productB1 but an expression was expected of type abstractProductA The second object type has no method methodB

See the full example here

glennsl
  • 28,186
  • 12
  • 57
  • 75