0

Abstract & Codes

I'm learning Golang and Nim which don't have class but has struct, and new to these kind of language. Being used to OOP I tried to make a class-like thing using struct but found that struct's fields are optional. I want to turn them mandatory in order to write strict code.

JAVA

class Person {
    String Name
    int Age
    Person(String Name, int Age) {
        this.Name = Name;
        this.Age = Age;
    }
}
// Ok
Person p1 = new Person("John Doe", 30);
// FAILS
Person p2 = new Person("John Doe");

Golang

type Person struct {
    Name    string
    Age     int
}
// Ok
p1 := Person{
    Name:   "John Doe",
    Age:    30,
}
// Ok
p2 := Person{
    Name:   "John Doe",
}

One of the solution is to implement a function that initializes struct; if arguments are not entirely passed it fails.

Golang

func newPerson(Name string, Age int) Person {
    return Person{
        Name:   Name,
        Age:    Age,
    }
}
// Ok
p1 := newPerson("John Doe", 30)
// FAILS
p2 := newPerson("John Doe")

Question

I feel the above solution redundant because init function has to come along with each struct. Is this method popular or there's better solution?

Takuya HARA
  • 499
  • 1
  • 3
  • 17
  • 1
    I think you should tag this question as golang. This shouldn't be language agnostic, because I know at least 2 languages where `struct`s don't work like this. – Sweeper May 03 '20 at 07:59
  • Thanks for your advise, I didn't know that. Which languages are you talking about and do they fail if arguments are not entirely passed? – Takuya HARA May 03 '20 at 08:12
  • 1
    C# and Swift are what I immediately thought of. Structs in C#/Swift have constructors/initialisers that work very similar to classes. – Sweeper May 03 '20 at 08:14
  • 1
    It's not that common that someone would want to implement an API where all fields need to be filled – most of the time a default value is good enough. Strict initializers like what you have in your examples are fairly normal. I don't know about the nuances of Java and Goland, but in C++ you would have a strict initializer that doesn't allow to instantiate the struct/class without initializing what you want. – mukunda May 03 '20 at 08:17
  • @Sweeper You're right, I actually confirmed in Swift. Thank you! – Takuya HARA May 03 '20 at 08:22
  • @mukunda Thank you, but could you please give me the detail why the API you say is not common? Just for my interest. – Takuya HARA May 03 '20 at 14:35
  • 1
    I can't give hard evidence of this offhand, but from my practice I can say that having to explicitly initialize every parameter every time seems like a tedious API, though I'm sure there are use cases for that where it makes sense (like actual data versus options for data). – mukunda May 03 '20 at 17:03
  • @mukunda Thanks! – Takuya HARA May 03 '20 at 17:33
  • Nim has `type`, that fills the object with default values. In your case, `var p = Person()` would create a Person object with `name = ""` and `age = 0`. `var p = Person(name: "John Doe")` creates a Person with `age = 0`. – xbello May 04 '20 at 07:46

1 Answers1

1

In Golang, you can have constructor-like factory functions (like the one you defined above) to initialize default values when initializing structs.

Yes, this is the correct solution and there are several advantages of choosing such solution. I have listed down some of them:

  1. You will implement a factory function only when necessary thus avoid unnecessary typing.
  2. Have complete control on the object construction i.e. if initialization doesn't succeed you can comfortably return an error by having function signature as func newPerson(Name string, Age int) (Person, error). In a constructor this is not possible.
  3. Implementing constructors in other languages is no different from implementing factory functions in Golang.

Apart from the above advantages, since you can directly instantiate struct where ever necessary, factory functions help in avoiding repetition for initializing default values.

Sai Ravi Teja K
  • 569
  • 4
  • 11