Inheritance of class variables to a subclass - oop

I'm having a huge nightmare with these subclasses and I can't figure out why this isn't working.
I have main class BODY with a subclass RECTANGLE. BODY has a function called SetWorld which does the following
function BODY:SetWorld( worldnum )
self.world = worldnum
end
Now, if I do this:
rect = RECTANGLE:new()
rect:SetWorld(1)
The value self.world is changed to 1 in the SetWorld function but if I try to use self.world in another function in BODY it always returns nil. Why is this? It works if I create a new BODY instead of a RECTANGLE, but that means I can't use my subclass.

When using a colon to call a method, the first argument is set the "self", and all other arguments are shifted. If you had supplied more code it would be easier to resolve the issue, however, I believe this may be the issue:
local x = {
new = function(o, t)
print("1st Arg", o)
print("2nd Arg", t)
end
}
x.new("Hello World")
x:new("Hello World")
Do you see how the arguments are shifted?

Related

pass value by reference in kotlin

I want to pass a value to a function so when I change the value outside that function I could see it updated in my function as well. I know that when I pass Boxed types like Int, Boolean etc they passed by value. But looks like classes are passed by value as well:
data class TestClass(var b:Boolean)
fun printBooleanIn1sec(b: TestClass) {
Thread.sleep(1000L)
println(b.b)
}
fun main(args: Array<String>) {
var testClass = TestClass(false)
printBooleanIn1sec(testClass)
testClass.b = true
}
// prints "false"
Is there a way to pass something by reference but not by value in Kotlin if I need it?
Class instances are always passed by value of the reference. So the reference used in the function is pointing to the same thing as the reference passed to it, but you never have direct access to pointers in Kotlin/Java. It's important to make this distinction because "pass by reference" would mean that the function could end up looking at a different object if the higher code on the stack changed what its variable was pointing at.
The reason your code prints false is that the Thread you're sleeping is the same one that called your function, and printBooleanIn1sec() returns before testClass.b = true is reached. To illustrate the situation you wanted, you would need to spin up a new thread that sleeps and then prints the value, like:
fun printBooleanIn1sec(b: TestClass) {
thread {
Thread.sleep(1000L)
println(b.b)
}
}
Primitives are abstracted away in Kotlin, so you don't have to think of them differently than a class. But like any other immutable class, you can't change their value at all when you pass them into a function. If you want to "see" changes in the function that occur elsewhere, you'll have to wrap them in classes that hold a var property for them.

Indirect initialization of memory via UnsafeMutablePointer types

I encountered an unfamiliar pattern of initialization from Objective-C that I'm struggling to replicate in Swift.
Objective-C
In the example code, they defined a C struct such as this (abbreviated, original here):
struct AQPlayerState {
AudioFileID mAudioFile;
}
Here's an example that uses AQPlayerState:
AQPlayerState aqData; // 1
OSStattus result =
AudioFileOpenURL(
audioFileURL,
fsRdPerm,
0,
&aqData.mAudioFile // 2
);
The key takeaway from above is that aqData currently has uninitialized properties, and AudioFileOpenURL is initializing aqData.mAudioFile on it's behalf.
Swift
I'm trying to replicate this behaviour in Swift. Here's what I've tried so far:
Models:
class Person {
var name: String
init(name: String) {
self.name = name
}
}
class Foo {
var person: Person?
}
My idea was to replicate the Objective-C code by passing a reference of Foo.person into a function that would instantiate it on it's behalf.
Initialization Function:
func initializeWithBob(_ ptr: UnsafeMutablePointer<Person?>) {
ptr.pointee = Person(name: "Bob")
}
initializeWithBob takes a pointer to an address for a Person? type and initializes it with a Person(name: "Bob") object.
Here's my test code:
let foo = Foo()
let ptr = UnsafeMutablePointer<Person?>.allocate(capacity: 1)
ptr.initialize(to: foo.person)
defer {
ptr.deinitialize()
ptr.deallocate(capacity: 1)
}
initializeWithBob(ptr)
print(foo.person) // outputs nil
initializeWithBob failed to "install" an instance of type Person in my Foo instance. I presume some of my assumptions are wrong. Looking for help in correcting my assumptions and understanding of this situation.
Thanks in advance!
You can achieve what you are looking for via withUnsafeMutablePointer(to:_:) like so:
let foo = Foo()
withUnsafeMutablePointer(to: &foo.person) { (ptr) -> Void in
initializeWithBob(ptr)
}
print(foo.person!.name) // outputs Bob
However, I wouldn't recommend this approach. IMHO it makes more sense to wrap the APIs you are working with in a C function that you can make 'nice' to call from Swift. The problem with your current approach is that this type of Swift is hard to read for Swift developers and also hard to read for Audio Toolbox developers.
#kelvinlau Is this what you were thinking of trying to achieve?
func initializeWithBob(_ ptr: UnsafeMutablePointer<Foo>) {
ptr.pointee.person = Person(name: "Bob")
}
let foo = Foo()
let ptr = UnsafeMutablePointer<Foo>.allocate(capacity: 1)
ptr.initialize(to: foo)
initializeWithBob(ptr)
print(foo.person?.name ?? "nil")
ptr.deinitialize()
ptr.deallocate(capacity: 1)
print(foo.person?.name ?? "nil")
The code pattern you have in Objective-C is for out parameters, that is parameters which return a value, or in out parameters, that is parameters which both pass a value in and return one. Objective-C does not directly support these so pointers are used to produce the semantics.
Swift has in out parameters indicated by the keyword inout in the function declaration. Within the function an assignment to an inout parameters effectively assigns a value to the variable that was passed as the argument. At the function call site the variable must be prefixed by & to indicate it is the variable itself and not its value which is effectively being passed.
Keeping your Person and Foo as is your function becomes:
func initializeWithBob(_ ptr: inout Person?)
{
ptr = Person(name: "Bob")
}
and it may be used, for example, like:
var example = Foo()
initializeWithBob(&example.person)
Using inout in Swift is better than trying to build the same semantics using pointers.
HTH
Note: You can skip this unless you are curious
"Effectively" was used a few times above. Typically out parameters are implemented by the parameter passing method call-by-result, while in out use call-by-value-result. Using either of these methods the returned value is only assigned to the passed variable at the point the function returns.
Another parameter passing method is call-by-reference, which is similar to call-by-value-result except that each and every assignment to the parameter within the function is immediately made to passed variable. This means changes to the passed variable may be visible before the function returns.
Swift by design does not specify whether its inout uses call-by-value-result or call-by-reference. So rather than specify the exact semantics in the answer "effectively" is used.

How do I pass parameter of inline new object?

I have a method that accepts a string as a parameter.
The string I need to pass is the property of an instantiated object.
I don't need the object to stick around once I get the value of that property.
I know I can do this like so:
Dim x As New myClass1
foo.thing1 = MyMethod(x.Name)
x = New MyClass2
foo.thing2 = MyMethod(x.Name)
'etc...
But I would prefer to do this inline if possible, since I have to do this several times in a row with different MyClass types.
EDIT:
Figured it out:
foo.thing = MyMethod(new MyClass().Name)
Try
foo.thing1 = MyMethod((New myClass1).Name)
foo.thing2 = MyMethod((New MyClass2).Name)
You need the braces around New myClass1, otherwise VB thinks you are trying to create an object of type myClass1.Name, which, of course, does not exist.
foo.thing = MyMethod(new MyClass().Name)

bad argument #2 to 'setmetatable' (nil or table expected)?

I currently stuck on this with a corona app I'm creating.
I have a file structure like below:
App -> Classes -> Objects -> Ships
In the App folder is the main.lua, menu.lua, level.lua and Class.lua. In the Classes folder there is Object.lua. In Objects, ship.lua and finally in the Ships are my different ships i.e. player and enemy.
I followed this tutorial and my code is almost completely identical to his (bar player and enemys classes), but still am receiving this error in the Class.lua is
"bad argument #2 to 'setetatable'(nil or table expected)"
The code I receive the error on is
function Class(Super)
Super = Super or Base
local prototype = setmetatable({}, Super) -- receive error here
prototype.class = prototype
prototype.super = Super
prototype.__index = prototype
return prototype
end
Base = Class()
function Base:new(...)
local instance = setmetatable({}, self)
instance:initialize(...)
return instance
end
function Base:initialize() end
function Base:get()
local Instances = self.Instances
if (not Instances[1]) then local obj = self:new() end
return table.remove(Instances, 1)
end
function Base:dispose()
table.insert(self.Instances, self)
end
I've tried changing the classes and changing the "setmetatable({},Super)" to "setmetatable(Super, self), putting all the classes in one file, I've read the lua docs, requiring the Class.lua in the mai, menu and the level.lua etc. and nothing has worked.
Any help would be greatly appreciated.
Thanks
function Class(Super)
Super = Super or Base
local prototype = setmetatable({}, Super) -- receive error here
prototype.class = prototype
prototype.super = Super
prototype.__index = prototype
return prototype
end
Base = Class()
Follow the execution of the code above.
You declare a function Class and then call it (and assign its returned value to Base).
Step through the execution of Class from the Base = Class() line.
function Class(Super)
The function takes one argument named Super
Super = Super or Base
You are allowing the Super argument to be nil/unpassed by using a default value of Base.
This call Base = Class() is not passing a value so this line Super = Super or Base has Super as nil and so evaluates to Super = nil or Base however the global Base is also nil as it has not yet been assigned to so you get Super = nil.
local prototype = setmetatable({}, Super)
This line then attempts to use Super (assigned from the line before) only it is, as we just saw, nil hence your error.
The bit from the tutorial that you missed (or at least missed in your posted snippet) is the crucially important local Base line above the Class function definition.

How to get the handle of a method in an Object (class inst) within MATLAB

I'm trying to grab a method handle from within an object in MATLAB, yet something in the sort of str2func('obj.MethodName') is not working
The answer is to get a function handle as #Pablo has shown.
Note that your class should be derived from the handle class for this to work correctly (so that the object is passed by reference).
Consider the following example:
Hello.m
classdef hello < handle
properties
name = '';
end
methods
function this = hello()
this.name = 'world';
end
function say(this)
fprintf('Hello %s!\n', this.name);
end
end
end
Now we get a handle to the member function, and use it:
obj = hello(); %# create object
f = #obj.say; %# get handle to function
obj.name = 'there'; %# change object state
obj.say()
f()
The output:
Hello there!
Hello there!
However if we define it as a Value Class instead (change first line to classdef hello), the output would be different:
Hello there!
Hello world!
One could also write
fstr = 'say';
obj.(fstr)();
This has the advantage that it does not require a handle class to work if the object (obj) is modified.
Use #. The following code works for me:
f = #obj.MethodName
No other answer mimics str2func('obj.MethodName'). Actually, this one doesn't either, not exactly. But you can define an auxillary function like so:
function handle = method_handle(obj, mstr)
handle = #(varargin) obj.(mstr)(varargin{:});
end
Then method_handle(obj, 'MethodName') returns a handle to obj.MethodName. Unfortunately, you cannot pass the variable name of obj as a string - eval("obj") will be undefined in the function's scope.