13

Let's say we're making a parser. One implementation could be:

public sealed class Parser1
{
    public string Parse(string text)
    {
       ...
    }
}

Or we could pass the text to the constructor instead:

public sealed class Parser2
{
    public Parser2(string text)
    {
       this.text = text;
    }

    public string Parse()
    {
       ...
    }
}

Usage is simple in both cases, but what does it mean to enable parameter input to Parser1, compared to the other? What message have I sent to a fellow programmer, when they look at the API? Also, are there any technical advantages/disadvantages in certain cases?

Another question comes up when I realize that an interface would be quite meaningless in the second implementation:

public interface IParser
{
    string Parse();
}

...where an interface on the first one could serve at least some purpose. Does that signify anything in particular, that a class is "interfaceable" or not?

1
  • This is the first time I have seen some useful Q & A about how the semantics of OO actually expresses intent. Up to now it has all just been syntactic sugar, to me.
    – user251748
    Commented Feb 28, 2018 at 18:22

5 Answers 5

12

Semantically speaking, in OOP you should only pass the constructor a set of parameters which are needed to build the class - similarly when you call a method, you should only pass it the parameters it needs to execute its business logic.

The parameters that you need to pass in the constructor are parameters which have no sensible default value and if your class is immutable (or indeed a struct) then all-non default properties must be passed.

Regarding your two example:

  • if you pass text to the constructor, it hints that the Parser2 class will be specifically built to parse that instance of text at a later time. It will be a specific parser. This is typically the case when building the class is very expensive or subtle, a RegEx might be compiled in the constructor, so once you hold an instance you can re-use it without having to pay the cost of compiling; another example is initializing the PRNG - it's better if it is done rarely.
  • if you pass text to the method, it signals that Parser1 can be reused to parse different texts by calls.
1
  • 5
    I'd add that there's a, weak, signal that Parser1 maintains state -- i.e. that a particular string of text may produce different results depending upon has previously been done on tat instance. This isn't necessarily so, but it may be.
    – jmoreno
    Commented Jun 5, 2013 at 6:31
10

Well, let's recall what it means to pass a variable as constructor parameter: You initialize an object in order to use its instance variables in methods of the object. The point is that you probably want to use it in more than one method since you want to have a high cohesion in your class.

Passing a parameter directly to a method means in a way sending a message to an object and probably receive an answer. By that, the client wants the object to deliver a service for him.

So in conclusion, those are two very different means of passing parameters and you should choose whether your object should either deliver a service or provide some functionality inherently while managing some information internally.

1
  • +1. Cohesion is the how I decide whether it belongs on the method or constructor.
    – jhewlett
    Commented Jun 5, 2013 at 0:51
4

Usage is simple in both cases, but what does it mean to enable parameter input to Parser1, compared to the other?

Its a fundamental design shift. And design should convey intent and meaning. Do you need to have separate objects for every string you want to parse? In other words, why do we need an instance of parser with stringX and another instance with stringY? What is it about parse(ing) and the given string that the two must live and die together? Assuming that the "underlying [parsing] implementation" (as Robert Harvey says) does not change, there seems to be no point. And even then its questionable IMHO.

How does the concept of a class change when passing data to the constructor instead of method parameters?

Constructor parameters tell me these things are required for an object. Proper state is not guaranteed without them. Also, I know how/why one parser is fundamentally different from another.

Constructor parameters keep me from having to know too much about how to use the class. If instead I'm supposed to set certain properties - how do I know that? A whole can of worms opens up. What properties? In what order? Before I use what methods? and so on.

Another question comes up when I realize that an interface would be quite meaningless in the second implementation:

An interface, as in A.P.I., is the methods and properties exposed to client code. Do not get wrapped up in public interface { ... } exclusively. So the meaning of the interface is in the either-or constructor vs method parameter dilemma, NOT public interface Iparser vs public sealed class Parser

The sealed class is odd. If I'm thinking about different parser implementations - you did mention "Iparser" - then inheritance is my first thought. It's just a natural conceptual extension in my thinking. I.E. all ParserXs are fundamentally Parsers. How else to say it?... A German Shepard is a dog (inheritance), but I can train my parrot to bark (act like a dog - "interface"); but Polly is not a dog, merely pretending, having learned a subset of dogness. Classes, abstract or otherwise, serve perfectly well as interfaces.

1
  • If it walks like a parser and talks like a parser, it is... a duck!
    – user251748
    Commented Feb 28, 2018 at 18:25
2

The second version of the class can be made immutable.

The interface can still be used to provide the ability to swap out the underlying implementation.

3
  • Can't it be made immutable in the first version too, by passing data around within the class in a functional manner?
    – ciscoheat
    Commented Jun 4, 2013 at 22:12
  • 2
    Absolutely. But the general pattern of immutability is to set the class members using the constructor, and have read-only properties. For functional programming, you don't even need a class. Commented Jun 4, 2013 at 22:48
  • The Scylla and Charybdis: do I choose OO or immutable data? I never heard it put that way before.
    – user251748
    Commented Feb 28, 2018 at 18:27
2

Parser1

Building with a default constructor and passing input text into a method implies that Parser1 is re-usable.

Parser2

Passing the input text into the constructor implies that a new Parser2 must be created for each input string.

3
  • Sure, so if we take it to the next level, what to conclude about a re-usable object compared to a non-reusable?
    – ciscoheat
    Commented Jun 4, 2013 at 20:26
  • I wouldn't assume any more than that, instead deferring to documentation. Commented Jun 5, 2013 at 13:35
  • A "re-usable object" where its identity changes is a non-sequitur. And with managed frameworks meaning that you don't even have to throw things away, just overwrite them or have them go out of scope, it is certainly unnecessary. Construct away!
    – user251748
    Commented Feb 28, 2018 at 18:30

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.