Static methods in base class not accesssible in derived class via "this".

Get help with using AutoHotkey (v2 or newer) and its commands and hotkeys
wpb
Posts: 150
Joined: 14 Dec 2015, 01:53

Static methods in base class not accesssible in derived class via "this".

01 Mar 2024, 12:05

I'm having trouble with an object derived from a base object with a static method. I need the derived class to be able to access the method via "this", rather than saying Base.Method().

Code: Select all

x := Child()


class Base
{
	static someMethod()
	{
		MsgBox("Hello")
	}
}

class Child extends Base
{
	__New()
	{
		this.someMethod()	; Fails. Need to use Base.someMethod()
	}
}
Is this possible? I use someMethod() in Base as a function that's called by code that doesn't expect to have an instance of Base (that's why someMethod() is static), but I also have code that expects to be able to call Child.someMethod(). Can the two situations co-exist somehow? Or do I need a pseudo-method in Child to call through to super?
iseahound
Posts: 1459
Joined: 13 Aug 2016, 21:04
Contact:

Re: Static methods in base class not accesssible in derived class via "this".

01 Mar 2024, 12:22

No it's not directly possible. You'll have to play around with either making the method static and calling super/prototype or making it an instance method and calling it using class.prototype.

If you want to support both forms you'll need a simple helper function.
teadrinker
Posts: 4389
Joined: 29 Mar 2015, 09:41
Contact:

Re: Static methods in base class not accesssible in derived class via "this".

01 Mar 2024, 12:50

Code: Select all

x := Child()

class Base
{
	static someMethod()
	{
		MsgBox("Hello")
	}
}

class Child extends Base
{
	__New()
	{
		Child.someMethod()
	}
}
wpb
Posts: 150
Joined: 14 Dec 2015, 01:53

Re: Static methods in base class not accesssible in derived class via "this".

01 Mar 2024, 19:41

Thanks, @teadrinker. That's interesting, but doens't help in situations like this:

Code: Select all


x := Child()
x.someMethod()


class Base
{
	static someMethod()
	{
		MsgBox("Hello")
	}
}

class Child extends Base
{
	__New()
	{
		MsgBox("Hello from child.")
	}
}
niCode
Posts: 315
Joined: 17 Oct 2022, 22:09

Re: Static methods in base class not accesssible in derived class via "this".

01 Mar 2024, 20:16

And it shouldn't. Class and instance methods are separate. Remove static to make it an instance method.

Code: Select all

x := Child()
x.someMethod()


class Base
{
	someMethod()
	{
		MsgBox("Hello")
	}
}

class Child extends Base
{
	__New()
	{
		MsgBox("Hello from child.")
	}
}
If this isn't what you're after, then it's best to say what exactly you're trying to achieve.
wpb
Posts: 150
Joined: 14 Dec 2015, 01:53

Re: Static methods in base class not accesssible in derived class via "this".

02 Mar 2024, 03:57

Thanks. The issue is this:
I have a cExcel class, which provides various helper functions for dealing with Excel. It's in my lib, and I use it from various scripts I've written, and all its methods are static, so I don't have to create a cExcel object, I just use, eg. cExcel.GetActiveWorkbook().
Now I have a more complex app that creates an instance of a cExcelAsDatabase class, which inherits from cExcel.
There are other database provider classes in the app, and they all have a common interface.
So other parts of the app expect to be able to call, e.g. databaseObjectInstance.GetCellCoords(), where the databaseObjectInstance could be either a cExcelAsDatabase or some other database class instance with the same interface.
But if the GetCellCoords() method is one of the static ones provided by cExcel, the app can't resolve databaseObjectInstance.GetCellCoords().
teadrinker
Posts: 4389
Joined: 29 Mar 2015, 09:41
Contact:

Re: Static methods in base class not accesssible in derived class via "this".

02 Mar 2024, 04:38

I can't get why not just call the static method directly through the class name where it is defined.
wpb
Posts: 150
Joined: 14 Dec 2015, 01:53

Re: Static methods in base class not accesssible in derived class via "this".

02 Mar 2024, 04:53

Because databaseObjectInstance might be some other type of object that isn't derived from cExcel. But it should still have a GetCellCoords() method. Does that make sense?

Perhaps I could define a __Call() method in the derived class that checks super for the relevant method? Not sure if that would work...
teadrinker
Posts: 4389
Joined: 29 Mar 2015, 09:41
Contact:

Re: Static methods in base class not accesssible in derived class via "this".

02 Mar 2024, 07:41

wpb wrote: Because databaseObjectInstance might be some other type of object that isn't derived from cExcel.
But static methods have nothing to do with instances.
Can you give a simple example that demonstrates the issue?
wpb
Posts: 150
Joined: 14 Dec 2015, 01:53

Re: Static methods in base class not accesssible in derived class via "this".

02 Mar 2024, 09:26

Perhaps this will illustrate what I mean:

Code: Select all

x := cGSheetsAsDatabase()
y := cExcelAsDatabase()

doSomethingWithCellCoords(x)	; Works
doSomethingWithCellCoords(y)	; Fails


doSomethingWithCellCoords(instanceOfDatabase)
{
	MsgBox(instanceOfDatabase.GetCellCoords())
}

class cExcel
{
	static GetCellCoords()
	{
		return "Excel hello"
	}
}

class cExcelAsDatabase extends cExcel
{

}

class cGSheetsAsDatabase
{
	GetCellCoords()
	{
		return "GSheets hello"
	}
}
Does that clarify the situation?
lexikos
Posts: 9665
Joined: 30 Sep 2013, 04:07
Contact:

Re: Static methods in base class not accesssible in derived class via "this".

02 Mar 2024, 22:43

Why do you instantiate subclasses of cExcel, but not instantiate cExcel itself? Be consistent, and there won't be a problem.

I think there is no good practical or semantic reason to define a "static class" (i.e. singleton object) and expect to use subclasses via instantiation. Perhaps you have started with a singleton Excel object, now want to expand to other database types. In that case, you should rethink the overall concepts. What are all of the objects? GSheets is not (an) Excel. GSheets should not derive from Excel; both should derive from a common base.

If you really want cExcel to be a singleton object (i.e. so you can call cExcel.Whatever() without explicitly instantiating it in each script), I think you should still define it as a normal class, with instance methods/properties. Then either instantiate it once and assign to a separate variable (perhaps in the #include file which defines the class, if applicable), or define static __New() to transform the class into an instance of itself. For the latter:
  • Set this.base := this.prototype (where this is the class itself) so that it "inherits" instance methods from its prototype, instead of inheriting static methods from its base class.
  • Call __init (if defined) so that instance properties are assigned.
  • Call the instance version of __new (if defined and meaningful).
There's some discussion and examples of singleton patterns in Dynamic global declaration workaround?.

This demonstrates the basic concept, but ignores instance variable declarations and constructors:

Code: Select all

class A {
    B() => MsgBox(A_ThisFunc)
}
class C extends A {
    static Base := this.Prototype
    B() {
        super.B()  ; This calls the version of B defined by A.
        MsgBox(A_ThisFunc)
    }
}
C.B()
wpb
Posts: 150
Joined: 14 Dec 2015, 01:53

Re: Static methods in base class not accesssible in derived class via "this".

03 Mar 2024, 09:49

Thanks for your thoughts. Understanding the object instantiation AHK uses is requiring a lot more power than I'm used to providing to my brain. Apologies if it takes a while to click.

As for why the design is as it is, it's because:
  1. cExcel makes sense as a singleton object, because it encapsulates helper functions to do with any running Excel instances, and as such only one of it needs to be in existence. Nice not to have to instantiate it in each script; just use cExcel.Whatever(), like you said above.
  2. cGSheetsAsDatabase has nothing to do with cExcel, and doesn't inherit from it. But it is expected to provide the same interface as cExcelAsDatabase, or any other xxxAsDatabase class. That includes some of the functionality that in the case of cExcelAsDatabase, is actually provided by cExcel.
  3. cExcelAsDatabase is similar to cExcel, but represents a distinct use-case of Excel as a database provider. It could also be a singleton object for the same reason as 1), but at the moment, it isn't. It makes sense that it inherits from cExcel, because it needs to provide a lot of the same functionality as cExcel. I could in my design have cExcelAsDatabase as a singleton as well, and that might be the best solution for me. But I can see a situation where you might want multiple instances of cExcelAsDatabase (to match running instances of Excel, for example), all of which would want to inherit from the static cExcel class.
I'll have a play around with static __New() and see if that sorts things out for me! Thanks again for your explanations.

Return to “Ask for Help (v2)”

Who is online

Users browsing this forum: No registered users and 27 guests