GTK4 Tutorial Pt. 3

Saturday, March 4, 2023 | Permalink

In this article, we're going to do some structural changes in existing Hello.vala file that we created in previous article. Following is the code we currently have in the Hello.vala file.

public class Hello {
  public void greet(string name) {
    stdout.printf("hello, world\n");
  }

  public static int main(string[] args) {
    string name = "world";
    Hello hello = new Hello();
    hello.greet(name);
    
    return 0;
  }
}

I don't think that main() should be within the Hello class as main() has nothing to do with Hello class and we should follow separation of concern.

public class Hello {
  public void greet(string name) {
    stdout.printf("hello, world\n");
  }
}

public static int main(string[] args) {
  string name = "world";
  Hello hello = new Hello();
  hello.greet(name);
  
  return 0;
}

As main() is not part of the class, we don't have to worried about public and static.

public class Hello {
  public void greet(string name) {
    stdout.printf("hello, world\n");
  }
}

int main(string[] args) {
  string name = "world";
  Hello hello = new Hello();
  hello.greet(name);
  
  return 0;
}

Let's run this program and confirm the output. It should not effect the output as we did structural changes for refactor.

$ valac Hello.vala && ./Hello
hello, world

Yes, it is working!

Even further, I don't think we should have the main() method within Hello.vala file at all. Because, Hello.vala file should suppose to the Hello class and nothing else. main() method is a special method and we should have it in the main.vala file.

Let's create a new file with name main.vala and cut-paste the main() method from Hello.vala file to newly created main.vala file. After doing this modification, we should have the following code in the Hello.vala file.

public class Hello {
  public void greet(string name) {
    stdout.printf("hello, world\n");
  }
}

Following is the code we now should have in the main.vala file.

int main(string[] args) {
  string name = "world";
  Hello hello = new Hello();
  hello.greet(name);
  
  return 0;
}

With these modifications, you or our colleague can easily guess from the file name that Hello.vala should contains the Hello class code and main.vala should contains main() method.

We now have two files instead of one. We need to compile both files at the same time otherwise it'll generate errors. In such a case, the command to run two or more file is follow.

$ valac Hello.vala main.vala -o Hello && ./Hello
hello, world

Here, we've compiled both Hello.vala and main.vala files using valac compiler. After successful compilation it'll generate an object file (-o) or an executable with name Hello. You can give any name you like, but Hello make more sense here. Finally, we're ran the executable and it print the hello, world as expected output.


Before I complete this article, I would like to cover one more concept in Vala and that is constructor. We'll cover the constructor in more details in future articles. But, in this article, I want to give a glimpse of it.

Continue with the name variable in our hello, world example, instead of passing name variable while calling the greet() method, it make more sense to pass it while creating an object in main.vala in following way.

int main(string[] args) {
  string name = "world";
  Hello hello = new Hello(name);
  hello.greet();
}

Notice, I removed the name from greet() method call and now passed it while creating an object from the Hello class. Based on this, we need to do some changes in Hello class to accepts this modification.

First, let's define the class attribute or class variable with name name in the Hello.vala file.

public class Hello {
  public string name;

  public void greet() {
    stdout.printf("hello, %s\n", name);
  }
}

Next, let's define a method with name Hello() i.g. same name as the class name that accepts the name parameter with type of string. This is our constructor method and it'll accept the arguments passed while creating an object or instance of this class. We can assigned this passed argument to created class variable using this keyword.

public class Hello {
  public string name;

  public Hello(string name) {
    this.name = name;
  }

  public void greet() {
    stdout.printf("hello, %s\n", name);
  }
}

Finally, within greet() method, instead of name, we need to write this.name to access the set value of the name variable.

public class Hello {
  public string name;

  public Hello(string name) {
    this.name = name;
  }

  public void greet() {
    stdout.printf("hello, %s\n", this.name);
  }
}

Our program now is back in shape to print the hello, world in the terminal. But, this type we've used class constructor in Vala. Let's run the programs and confirm.

$ valac Hello.vala main.vala -o Hello && ./Hello
hello, world

Yeah. It is working!

I don't want to hold you more with this article. Enjoy rest of the day. See you in the next chapter after sometime.

Labels: ,