30log is not polymorphic?

Questions about the LÖVE API, installing LÖVE and other support related questions go here.
Forum rules
Before you make a thread asking for help, read this.
Post Reply
User avatar
modiX
Citizen
Posts: 73
Joined: Mon Dec 04, 2017 1:47 am

30log is not polymorphic?

Post by modiX » Thu Jan 11, 2018 12:09 pm

Hiho lövely fellows,

it seems that 30log does not follow all definitions of OOP, thus not fulfilling my desire. Maybe I lack to know how this is done right in 30log, so I want to ask for advice.

Polymorphic code allows child classes to effectively override functions of the parent classes. The object itself ends up with different/new implementations of the base functions. If the parent class code executes a function that is overridden in the child class, it will jump into the child implementation, since the base implementation is not existent on the object, anymore.

Here is a brief example how it should work, written in C# (because its OOP and its syntax is easy):

Code: Select all

using System;

class A {
	public A() {
		Console.WriteLine(test());
	}
	protected virtual string test() {
		return "A";
	}
}
class B : A {
	public B() : base() {
	}
	protected override string test() {
		return "B";
	}
}
public class Program
{	
	public static void Main()
	{
		new A(); // prints "A"
		new B(); // prints "B"
	}
}
.NET Fiddle to test the code: https://dotnetfiddle.net/F6vpbM

Here is a similar implementation of the above code using lua and 30log:

Code: Select all

local class = require "30log"

local A = class("A")
function A:init()
  print(self.test())
end
function A:test()
  return "A"
end

local B = A:extend()
function B:init()
  B.super:init()
end
function B:test()
  return "B"
end

A() -- prints "A"
B() -- should print "B", but prints "A"
Repl.it to test the code: https://repl.it/repls/GivingFuchsiaDamselfly (it includes 30log, scroll down for the code)

The problem is very obvious. The constructor of B calls the constructor of A. The constructor of A prints the returned value of the test function. Since the test function is overridden in B, it should use the test function of B, even when called by A, since the object is B that inherits from A, not A. 30log, however, does not do this. It uses only the implementation on the class that it was called from.

Since lua has no real OOP and just works with tables, I see the problem. the super table of B has the test implementation of A. Imo, it should somehow know that the test function was overridden in B and call this instead, or do I do something wrong here?
───▄▀▀▀▄▄▄▄▄▄▄▀▀▀▄───
───█▒▒░░░░░░░░░▒▒█───
────█░░░░░░░░░█────
▄▄──█░░░▀█▀░░░█──▄▄
█░░█▀▄░░░░░░░▄▀█░░█

Visual Studio Code Template

User avatar
modiX
Citizen
Posts: 73
Joined: Mon Dec 04, 2017 1:47 am

Re: 30log is not polymorphic?

Post by modiX » Thu Jan 11, 2018 12:29 pm

For anybody facing the same issue, I got help on Discord by alloyed.

The problem is how I call the base constructor. Instead of

Code: Select all

B.super:init()
I've to use

Code: Select all

B.super.init(self)
otherwise I give super to the base and super does not include my overridden implementations.
───▄▀▀▀▄▄▄▄▄▄▄▀▀▀▄───
───█▒▒░░░░░░░░░▒▒█───
────█░░░░░░░░░█────
▄▄──█░░░▀█▀░░░█──▄▄
█░░█▀▄░░░░░░░▄▀█░░█

Visual Studio Code Template

User avatar
zorg
Party member
Posts: 2287
Joined: Thu Dec 13, 2012 2:55 pm
Location: Absurdistan, Hungary
Contact:

Re: 30log is not polymorphic?

Post by zorg » Thu Jan 11, 2018 2:20 pm

modiX wrote:
Thu Jan 11, 2018 12:29 pm
I've to use

Code: Select all

B.super.init(self)
otherwise I give super to the base and super does not include my overridden implementations.
Note that self isn't magic in that context; you'd need to do

Code: Select all

B.super.init(B)
(which is what you wanted) at the call site, since self as an implicit thing can only exist in a function definition if it's done with the colon syntax. In short, B wasn't named self, so it wouldn't have worked that way.
Me and my stuff :3True Neutral Aspirant. Why, yes, i do indeed enjoy sarcastically correcting others when they make the most blatant of spelling mistakes. No bullying or trolling the innocent tho.

User avatar
modiX
Citizen
Posts: 73
Joined: Mon Dec 04, 2017 1:47 am

Re: 30log is not polymorphic?

Post by modiX » Sat Jan 13, 2018 12:51 am

zorg wrote:
Thu Jan 11, 2018 2:20 pm
Note that self isn't magic in that context; you'd need to do

Code: Select all

B.super.init(B)
(which is what you wanted) at the call site, since self as an implicit thing can only exist in a function definition if it's done with the colon syntax. In short, B wasn't named self, so it wouldn't have worked that way.
What? I'm confused. When I call B() anywhere outside self is B, it's not? I think I still lack understanding how 30log really works under the hood, can you clarify even more?
───▄▀▀▀▄▄▄▄▄▄▄▀▀▀▄───
───█▒▒░░░░░░░░░▒▒█───
────█░░░░░░░░░█────
▄▄──█░░░▀█▀░░░█──▄▄
█░░█▀▄░░░░░░░▄▀█░░█

Visual Studio Code Template

User avatar
zorg
Party member
Posts: 2287
Joined: Thu Dec 13, 2012 2:55 pm
Location: Absurdistan, Hungary
Contact:

Re: 30log is not polymorphic?

Post by zorg » Sat Jan 13, 2018 4:38 am

Code: Select all

local class = require "30log"

local A = class("A")
function A:init()
  print(self.test())
end
function A:test()
  return "A"
end

local B = A:extend()
function B:init()
  B.super.init(B) -- <- talking about this;
end
function B:test()
  return "B"
end

A() -- prints "A"
B() -- should print "B", but prints "A"
although now i realize that self does work here, but again, it's way more clearer to write it out completely in my opinion.
Me and my stuff :3True Neutral Aspirant. Why, yes, i do indeed enjoy sarcastically correcting others when they make the most blatant of spelling mistakes. No bullying or trolling the innocent tho.

User avatar
kikito
Inner party member
Posts: 3142
Joined: Sat Oct 03, 2009 5:22 pm
Location: Madrid, Spain
Contact:

Re: 30log is not polymorphic?

Post by kikito » Thu Jan 18, 2018 2:49 pm

I don't know the internals of 30log, but in middleclass you have to pass self to superclass constructors, not the class. I remember giving this a great deal of thought back in the day, and there was no other way. self is indeed "magical" inside constructors.

I would be very surprised if 30log worked in a different way, as zorg is suggesting. I think you must pass self.
When I write def I mean function.

User avatar
modiX
Citizen
Posts: 73
Joined: Mon Dec 04, 2017 1:47 am

Re: 30log is not polymorphic?

Post by modiX » Sat Jan 20, 2018 10:09 pm

So in my test passing B didn't work, but passing self did. I agree with you, kikito.
───▄▀▀▀▄▄▄▄▄▄▄▀▀▀▄───
───█▒▒░░░░░░░░░▒▒█───
────█░░░░░░░░░█────
▄▄──█░░░▀█▀░░░█──▄▄
█░░█▀▄░░░░░░░▄▀█░░█

Visual Studio Code Template

Post Reply

Who is online

Users browsing this forum: No registered users and 7 guests