Mixins + Inheritance

Bugs that have been investigated and resolved somehow.

Moderator: GZDoom Developers

Forum rules
Please don't bump threads here if you have a problem - it will often be forgotten about if you do. Instead, make a new thread here.
Post Reply
User avatar
4page
Posts: 120
Joined: Tue Aug 06, 2019 5:08 pm
Location: American Pacific Northwest

Mixins + Inheritance

Post by 4page »

Not sure if this is a bug or not. When using a mixin on a class which also inherits from a different class I realized they both (the mixin and the parent class) had a function with the same name. The game ran fine, and when I checked it seemed that it was running the mixin version of the function. I was told this might be a bug and to make an example to post here, but when I made the example it would only run the parent class function. And if there are 2 mixins that have the same function as the parent class then the game won't run as it sees the duplicate between the parent and the 2nd mixin, but not the first.

Spawn the Test_Child class, or uncomment the Test_Mixin2 line to see.

Code: Select all

Mixin Class Test_Mixin1
{
	void Test_Function()
	{
		console.printf(string.format("This is the mixin #1"));
	}
}

Class Test_Parent : ACTOR
{
	void Test_Function()
	{
		console.printf(string.format("This is the Parent Actor"));
	}
	Default
	{
		+NOINTERACTION;
	}
	States
	{
		Spawn:
			TNT1 A 0 Nodelay Test_Function();
			Stop;
	}
}

Mixin Class Test_Mixin2
{
	void Test_Function()
	{
		console.printf(string.format("This is the mixin #2"));
	}
}

Class Test_Child : Test_Parent
{
	Mixin Test_Mixin1;
	//Mixin Test_Mixin2;
}
User avatar
Graf Zahl
Lead GZDoom+Raze Developer
Lead GZDoom+Raze Developer
Posts: 49073
Joined: Sat Jul 19, 2003 10:19 am
Location: Germany

Re: Mixins + Inheritance

Post by Graf Zahl »

This behaves as would be expected. The mixin function takes priority due to how mixins are handled by the compiler.
User avatar
phantombeta
Posts: 2090
Joined: Thu May 02, 2013 1:27 am
Operating System Version (Optional): Windows 10
Graphics Processor: nVidia with Vulkan support
Location: Brazil

Re: Mixins + Inheritance

Post by phantombeta »

4page wrote:Not sure if this is a bug or not. When using a mixin on a class which also inherits from a different class I realized they both (the mixin and the parent class) had a function with the same name. The game ran fine, and when I checked it seemed that it was running the mixin version of the function. I was told this might be a bug and to make an example to post here, but when I made the example it would only run the parent class function. And if there are 2 mixins that have the same function as the parent class then the game won't run as it sees the duplicate between the parent and the 2nd mixin, but not the first.
This is indeed not a bug, and it's not related to mixins, either.

For specifics on what's going on here: This is called function hijacking, or shadowing¹. ZScript² allows you to define a new non-virtual function with the same name as one in a base class. However, since it's not virtual³, the only way for the compiler to know it exists is if the variable or expression is typed as the type that shadows the function or one of its descendants.
The reason it can still call the "correct" function when typed as the shadowing type is because the compiler first searches for the symbol⁴ in the class' own list of symbols - if not found, it then looks for it in the parent's list, then the parent's parent's list, and so on. Since the class' own list is searched first, the function that's doing the shadowing is also the one that's found first.

Code: Select all

class Foo {
    void SomeFunction () { /* [...] */ }
}

class Bar : Foo {
    // This shadows the original SomeFunction defined in "Foo"
    void SomeFunction () { /* [...] */ }
}

class Baz {
    void A () {
        Foo a = new ("Foo");
        Bar b = new ("Bar");
        Foo c = bar;

        a.SomeFunction (); // This will call Foo's SomeFunction
        b.SomeFunction (); // This will call Bar's SomeFunction
        c.SomeFunction (); // This will call Foo's SomeFunction
    }
}

¹: Also known as "symbol⁴ hijacking" or "symbol shadowing" in the general case.
²: And many other languages too. However, as far as I know nowadays it's not too common in new languages, because it only leads to bugs - there's not really any situation in which it won't cause needless confusion.
³: This is because virtual functions work differently than non-virtual ones - it chooses the function that needs to be called entirely at runtime, usually through something called a vtable, which is a list containing pointers to all the virtual functions of the type.
⁴: This is a term used to refer to the names of things like variables, functions, classes, etc.
Post Reply

Return to “Closed Bugs [GZDoom]”