Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Instantiate a Raku class, and update an instance variable in the constructor

Tags:

raku

I seem to be having difficulty understanding how to correctly work with classes in Raku.

I am trying to create a 'Database' class that I will use throughout my cro application. However I don't seem to understand how to deal with setting instance variables at object construction (BUILD?) time.

The class below shows an example of the problem I am having when calling it with:

Calling:

my $db = Database.new(dsn => 'update me!');
say "what value is foo: " ~ $db.what-is-foo(); # prints "what value is foo: 0" but expecting 123

My Class:

use DB::Pg;

class Database {
    has Str    $.dsn is required;
    has DB::Pg $!dbh = Nil;
    has Int    $!foo = 0;

    method new (:$dsn) {
        my $dbh = DB::Pg.new(conninfo => :$dsn);
        my $foo = 123;
        return self.bless(:$dsn, dbh => $dbh, foo => $foo);
    }

    method what-is-foo() {
        return $!foo;
    }
}

So in my class constructor I would like to pass in a named arg for the database dsn. In the new method I plan to connect, and set an instance variable to the connection handle.

In this example I am using a simple integer (foo) as a test.

So far I have found the docs here to not include an example of this type of pattern, except pehaps:

use DB::Pg;

class Database {
    has Str    $.dsn is required;
    has DB::Pg $!dbh = Nil;
    has Int    $!foo = 0;

    submethod BUILD(:$dsn) {
        $!dbh = DB::Pg.new(conninfo => :$dsn);
        $!foo = 123;
    }

    method what-is-foo() {
        return $!foo;
    }
}

But that gives me:

The attribute '$!dsn' is required, but you did not provide a value for it.

Any help would be greatly appreciated!

like image 201
camstuart Avatar asked Feb 17 '21 05:02

camstuart


People also ask

What is class variable and instance variable in Python?

A class variable is a variable that defines a particular property or attribute for a class. An instance variable is a variable whose value is specified to the Instance and shared among different instances. 2. We can share these variables between class and its subclasses. We cannot share these variables between classes.

How do you create a class level variable in Python?

Create Class VariablesA class variable is declared inside of class, but outside of any instance method or __init__() method. By convention, typically it is placed right below the class header and before the constructor method and other methods.

How do you create an instance of a class in Python?

To create instances of a class, you call the class using class name and pass in whatever arguments its __init__ method accepts.

What is instance variable in Python?

What is an Instance Variable in Python? If the value of a variable varies from object to object, then such variables are called instance variables. For every object, a separate copy of the instance variable will be created. Instance variables are not shared by objects.

How do you create an instance variable in a class?

Create Instance Variables Instance variables are declared inside a class method using the self keyword. We use a constructor to define and initialize the instance variables. Let’s see the example to declare an instance variable in Python.

Should variables be initialized in the constructor or outside the constructor?

Initializing variables outside the constructor can be easier to read, but removes some flexibility. Initializing in the constructor lets the arguments be passed as field values and allows for exception handling.

How to make a class’s instance callable?

To make a class’s instance callable, you need to implement a .__call__ () special method, which has nothing to do with Python’s instantiation process. You trigger Python’s instantiation process whenever you call a Python class to create a new instance. This process runs through two separate steps, which you can describe as follows:

What is object construction or instantiation?

This step is often referred to as object construction or instantiation. The tool responsible for running this instantiation process is commonly known as a class constructor. In Python, to construct an object of a given class, you just need to call the class with appropriate arguments, as you would call any function:


Video Answer


1 Answers

Only attributes with public accessors (that is, the . twigil) are set automatically with bless.

You have two ways to handle this. You can set them at TWEAK or BUILD, or you can add the attribute is built to the attribute to have this done automatically for you. The attribute is built is probably the easiest in this case, just say has Int $!foo is built = 0. But it's worth expanding on the other options:

If you include a BUILD method, you are responsible for all of the set up on your own. This means both public and private attributes. But you can make your life easier by smartly naming the parameters:

method BUILD (:$!dsn, :$!dbh, :$!foo) { }

That's actually it. The signature binds the incoming values to $!dsn, etc., which of course sets them for the whole object instance. Of course, you can do fancier things here too. In any case, after BUILD, there are some additional checks done. (1) if you don't set $!dsn, because you have is required, there will be an error. (2) if you don't ultimately set $!foo or $!dbh, they will receive their default value.

With TWEAK, you get passed the same arguments as you would with BUILD, but all initial set up is done (BUILD or the auto-binding to public attributes, and all default values, plus guarantee that required values are there). You just get a chance to do some last second adjustments.

like image 74
user0721090601 Avatar answered Oct 19 '22 06:10

user0721090601