I have a superclass called DatabaseObject. This class implements the Active Record design pattern and will be inherited by all the others that access the database.
In PHP, I was able to write like this:
class DatabaseObject {
protected static $database;
...
public static function set_database($database) {
self::$database = $database;
}
public static function find_all() {
$sql = "SELECT * FROM " . static::$table_name;
return static::find_by_sql($sql);
}
protected static function instantiate($record) {
$object = new static;
foreach($record as $property => $value) {
if( property_exists($object, $property) ) {
$object->$property = $value;
}
}
return $object;
}
...
}
Note the dynamic way of refer to the class using the keywords self::
and static::
. In that language we can even do things like this:
$object = new static;
In Python, we can create an instance of a class like so:
@classmethod
def _instantiate(cls, record):
# Creates an instance of the subclass.
obj = cls
In TypeScript, we can do similar things like:
protected static instantiate(record: object): object {
const obj = new this();
...
return obj;
}
How can I achieve the same result in PowerShell?
For now, I am only able to do it like this:
static [void]SetDatabase($Database) {
[DatabaseObject]::Database = $Database
}
I have to explicitly write the class name. If the class is supposed to be inherited, it is not going to work.
Can you tell me the correct way to do it?
Thank you.
Update (after the contribution of @Santiago Squarzon):
To clarify and possibly help others in the future, I will give more details.
The class has instance properties and methods, but I chose not to show them to keep things clear.
The static methods should be able to set static properties and call (passing arguments) other static methods.
Setting the return type, in the static methods, to custom types (instances of the subclass) would be a problem. But it is always possible to return an ArrayList containing the instance of the subclass.
The equivalent of self
in PowerShell would be $this
but can only be used on instance methods not static ones. Basically, if you want to dynamically reflect on the type members from a static method, the best you can do is to pass the type itself as argument. In addition, not sure how useful it will be to inherit from a class which has static members only but you may have a good reason. See about Classes for more details.
class Test {
static [string] $Prop
# with an instance method, can use `$this`
[void] SetProp([string] $Value) {
$this::Prop = $value
}
# with a static method, need to pass the target type
static [void] SetProp([type] $TargetType, [string] $Value) {
$TargetType::Prop = $Value
}
}
[Test]::new().SetProp('foo')
[Test]::Prop # foo
[Test]::SetProp([Test], 'bar')
[Test]::Prop # bar
As aside, you might find much better class support for what it seems you're looking to do using C# than PowerShell, in C# you don't need to refer to the type itself to assign the value of your property.
For example:
Add-Type '
public static class Test
{
public static string Prop { get; private set; }
public static void SetProp(string value)
{
Prop = value;
}
}
'
[Test]::Prop = 'foo' # Errors with ReadOnly property
[Test]::SetProp('foo')
[Test]::Prop # Outputs foo
Yet, you will find soon enough that you can't inherit from a static class which hints what is noted above. You might need to reconsider what you're looking to do. Most likely should use an instance method and an instance property.
Static classes are sealed and therefore cannot be inherited. They cannot inherit from any class or interface except Object.
See Static Classes and Static Class Members (C# Programming Guide).