2

I want to have a class that has a number of fields such as String, Boolean, etc and when the class is constructed I want to have a fieldname associated with each field and verify the field (using regex for strings). Ideally I would just like specify in the constructor that the parameter needs to meet certain criteria.

Some sample code of how :

case class Data(val name: String ..., val fileName: String ...) {
  name.verify
  // Access fieldName associated with the name parameter.
  println(name.fieldName) // "Name"
  println(fileName.fieldName) // "File Name"
}

val x = Data("testName", "testFile")
// Treat name as if it was just a string field in Data
x.name // Is of type string, does not expose fieldName, etc

Is there an elegant way to achieve this?

EDIT: I don't think I have been able to get across clearly what I am after. I have a class with a number of string parameters. Each of those parameters needs to validated in a specific way and I also want to have a string fieldName associated with each parameter. However, I want to still be able to treat the parameter as if it was just a normal string (see the example).

I could code the logic into Data and as an apply method of the Data companion object for each parameter, but I was hoping to have something more generic.

Stephan
  • 191
  • 1
  • 8
  • Was it a typo where you wrote "does not expose fieldName"? – Randall Schulz Feb 14 '13 at 00:10
  • I updated the code sample to make it clearer. I want to attach a parameter fieldName to each constructor parameter but I don't want that to be exposed to the outside. – Stephan Feb 14 '13 at 01:44
  • 2
    OK, but... where does this `fieldName` come from? You can always add `private val` in the body of a `case class`, if that suffices. – Randall Schulz Feb 14 '13 at 01:50
  • That is what I want to know. I want to be able to wrap around parameters logic to both validate the parameter as well as store information about it. My question is, is there an idiomatic way in Scala to do this. – Stephan Feb 17 '13 at 22:47
  • I'm sorry, but I don't understand what you're trying to do. – Randall Schulz Feb 17 '13 at 22:52

1 Answers1

3

Putting logic (such as parameter validation) in constructors is dubious. Throwing exceptions from constructors is doubly so.

Usually this kind of creational pattern is best served with one or more factory methods or a builder of some sort.

For a basic factory, just define a companion with the factory methods you want. If you want the same short-hand construction notation (new-free) you can overload the predefined apply (though you may not replace the one whose signature matches the case class constructor exactly).

If you want to spare your client code the messiness of dealing with exceptions when validation fails, you can return Option[Data] or Either[ErrorIndication, Data] instead. Or you can go with ScalaZ's Validation, which I'm going to arbitrarily declare to be beyond the scope of this answer ('cause I'm not sufficiently familiar with it...)

However, you cannot have instances that differ in what properties they present. Not even subclasses can subtract from the public API. If you need to be able to do that, you'll need a more elaborate construct such as a trait for the common parts and separate case classes for the variants and / or extensions.

Randall Schulz
  • 26,420
  • 4
  • 61
  • 81
  • 2
    Do you mean one shouldn't throw exceptions in constructors on exceptional situations? How about having `require` assertions in the constructor? – ziggystar Feb 14 '13 at 08:56
  • I try to avoid exceptions these days (confining them to as close to where some other code might generate them as possible) and I find exceptions in constructors particularly messy. And yes that includes `require` and `assert`. I refer you to http://stackoverflow.com/questions/9169691/how-to-check-constructor-arguments-and-throw-an-exception-or-make-an-assertion-i – Randall Schulz Feb 14 '13 at 15:12
  • I was talking about the situation where something unanticipated happens, because of a bug or something. Usually, you want your program to crash then, because you don't know what to do anyway. If the "exceptional" situation is anticipated (like malformed user input), then - yes - don't use exceptions, but otherwise? – ziggystar Feb 14 '13 at 15:27
  • Sure. In general you cannot prevent it, for one thing. But to deliberate throw (overtly or with `assert` / `require`) is something I avoid. YMMV (as we used to say a lot...). – Randall Schulz Feb 14 '13 at 15:35
  • Hi Randall, I agree with you on exceptions in principle. Unfortunately, the rest of the code is written using exceptions and consists of a mix of Scala and Java. I'm happy for the validation code to exist outside the constructor in a factory apply method. However, I need to be able to access the fieldName that has been assigned to a parameter inside the actual class. I will edit the question to try and make it clearer. – Stephan Feb 17 '13 at 22:52
  • I agree with @RandallSchulz on avoiding the use of exceptions. I am hitting the same area; validating case class parameters. I just posted something about it on StackOverflow's sister site, CodeReview. If you have time to look it over, I would appreciate any feedback you might have on it; i.e. help reducing boilerplate, better methods for approaching the problem space, etc.: http://codereview.stackexchange.com/questions/60645/reducing-boilerplate-when-validating-parameters-and-using-a-tuple-for-the-parame – chaotic3quilibrium Aug 20 '14 at 23:11