So, for example, I have classes of vegetables for a farm.
TVegetable = class
TCarrot = class(TVegetable)
TTomato = class(TVegetable)
I need two different classes of each vegetable, one for supermarkets and another for factories.
TCarrotSupermarket = class(TCarrot)
TCarrotFactory = class(TCarrot)
These classes are identical except the code for one method:
procedure Utilization;
TCarrotSupermarket.Utilization works with supermarkets, TCarrotFactory.Utilization works with factories.
One identical code for Utilization I need for
TCarrotSupermarket.Utilization, TTomatoSupermarket.Utilization, TPotatoSupermarket.Utilization, and another code for
TCarrotFactory.Utilization, TTomatoFactory.Utilization, TPotatoFactory.Utilization.
What is the best way to write code for Utilization only twice (for supermarkets and factories) and use it in a proper classes?
Welcome to Pattern Design. Your case is Strategy patternn
class TStrategyVegetable = class(TVegetable)
FUtil: TUtilization
public
procedure Create(util: TUtilization);
procedure Utilization();
end
procedure TStrategyVegetable.Create(util: TUtilization)
begin
FUtil := util
end
procedure TStrategyVegetable.Utilization;
begin
FUtil.Utilization;
end
Then in code:
carrotSupermarket = TCarrotSupermarket.Create(TCarrotSupermarketUtil.Create);
carrotFactory = TCarrotFactory.Create(TCarrotFactoryUtil.Create);
Here's some pseudo code getting to a solution with using interface method resolution. (Untested, not even compiled, but it should point you in the right direction)
IFactoryInterface=interface(IUnknown) ['{someGUID}']
procedure Utilization;
end;
ISuperMarketInterface=interface(IUnknown) ['{AnotherGUID}']
procedure Utilization;
end;
TVegetable = class (TSomeObject,IFactoryInterface,ISupermarketInterface)
protected
// the routines tha do the actual implementation
// can be regular virtual, dynamic, or whatever
procedure FactoryUtilization;
procedure SuperMarketUtilization;
// link up the interfaces using method resolution
procedure IFactoryInterface.Utilization=FactoryUtilization;
procedure ISupermarketInterface.Utilization=SuperMarketUtilization;
{ in case not derived from TInterfacedObject,
You'll have to add _AddRef,_Release and
QueryInterface methods too }
end;
// the other implementations can be as before
TCarrot = class(TVegetable)
TTomato = class(TVegetable)
Then when using the code it should look something like this:
VAR lSOmeVegetable,lAnotherVegetable:TVegetable;
...
lSomeVegetable:=TCarrot.Create
lanotherVegetable:=Tomato.Create
...
// call using buolt-in type checking
(lSOmeVegetable as IFactoryInterface).Utilization;
(lAnotherVegetable as ISuperMarketInterface).Utilization;
Or otherwise using the supports routine
VAR lFactory:IFactoryInterface;
...
if supports(lSomeVegetable,IFactoryInterface,lFactory) then
lFactory.Utilization
...
Hopefully this will help you a little. Here's a pointer to some matching documentation
Related
In this article (https://blogs.mathworks.com/loren/2012/07/16/who-what-why-but-not-this/) near the bottom Loren says that class properties can be the same as keywords. However, how is this possible? If you write a classdef script any attempt to use a keyword (including class keywords like "events") in the properties block gets a red syntax error. Was she mistaken? I'm asking because I really want a property name to be a keyword for a particular application.
Its possible by the use of dynamic properties, for example:
classdef test < dynamicprops
methods
function obj = test()
end
end
end
var = test();
var.addprop ( 'events' );
var.events = 123;
It can make code harder to maintain and its a bit overkill if you only want to name a single property the same as a keyword, in that instance why dont you do something like capitilizing the var name, or prepending it with something - so it still reads like what you want but it doesn't cause the name clash:
classdef test
properties
Events
myIf
% etc...
end
methods
function obj = test()
end
end
end
In MATLAB, one of the attributes of a class (defined after classdef) is Sealed, which means that no class can use it as a superclass (or to be more precise, "to indicate that these classes have not been designed to support subclasses."1).
For example, if I try to instantiate a class that's defined as below (considering table is Sealed):
classdef SomeLie < table
end
I would get the 'MATLAB:class:sealed' error:
>> A = SomeLie;
Error using SomeLie
Class 'table' is Sealed and may not be used as a superclass.
As I refuse to be told by a machine what I may or may not do, I would like to subclass a Sealed class, regardless. How can I do that in MATLAB R2017a?
I'm having a hard time believing that this system is completely airtight, so I'm looking for a solution that would cause the Sealed attribute to be silently ignored (or something of that sort). The desired solution should work without modifying any "library class definitions" to remove Sealed from them.
I tried playing around with "reflection", but arrived at a dead end...
classdef SomeLie % < table
properties (Access = private)
innerTable table;
end
properties (GetAccess = public)
methodHandles struct = struct();
end
methods
function slObj = SomeLie(varargin)
slObj.innerTable = table(varargin{:});
% methodHandles = methods(slObj.innerTable);
ml = ?table; ml = {ml.MethodList.Name}.';
ml = setdiff(ml,'end');
tmpStruct = struct;
for indM = 1:numel(ml)
tmpStruct.(ml{indM}) = str2func([...
'#(varargin)' ml{indM} '(slObj.innerTable,varargin{:})']);
end
slObj.methodHandles = tmpStruct;
end
function varargout = subsref(slObj,varargin)
S = struct(slObj);
varargout{:} = S.methodHandles.(varargin{1}.subs)(varargin{:});
end
end
end
(There's no need to fix the above code, I was just sharing)
I do not think the machine is the problem, but the class designer and he certainly has good motivations to seal the class. "Philosophy" of coding, a part, you could 'own' the class in a wrapper class without defining it sealed.
For example, supposer the class Hello is sealed and has a method (or function, if you wish) sayHello which you would like to use in inherited classes you could define a class FreeHello (public) which contains an instance of Hello. At the constructor you build the corresponding Hello and then you define a sayHello method whose body simply calls your Hello instance and makes it execute the sayHello method (and returns the output, accordingly).
In order to 'open' the sealed class, you need to do these for all properties and public methods; of course you are still not capable of accessing private methods, but now you can subclass your wrapper class, as you wish.
I'm trying to use procedures within a structured data type as callback functions for a program using GTK+3 as its toolkit in FreePascal. (The GTK+3 bindings I have were generated by the gir2pascal tool (http://wiki.freepascal.org/gir2pascal))
In the example below, I use advanced records, but I would definitely consider classes or objects if it works better/at all with them.
The problem that occurs is that when the callback procedure is called, it cannot access anything else within its own record. It seems to "forget" where it comes from.
For instance, in the example below I have the integer myRecord.myInt, that I can set and retrieve happily by calling the procedure myRecord.testProcedure. However when testProcedure is used as a C callback (when I click the button), I will receive some number (e.g. 30976), but not 7.
{$MODESWITCH ADVANCEDRECORDS}
uses gobject2, gtk3, math;
type
myRecord=record
public
myInt: Integer;
procedure testProcedure; cdecl;
end;
procedure myRecord.testProcedure; cdecl;
begin
WriteLn(myInt);
end;
var
recordInstance: myRecord;
button, win: PGtkWidget;
begin
SetExceptionMask([exDenormalized, exInvalidOp, exOverflow,
exPrecision, exUnderflow, exZeroDivide]); {this is needed for GTK not to crash}
gtk_init(#argc, #argv);
win:=gtk_window_new(GTK_WINDOW_TOPLEVEL);
recordInstance.myInt:=7;
button:=gtk_button_new;
{The following does not work. The procedure will run when the button is
clicked; it will print some number, but not the content of recordInstance.myInt}
g_signal_connect_data(button, 'clicked',
TGCallback(#recordInstance.testProcedure), nil, nil, 0);
{add button to window}
gtk_container_add(PGtkContainer(win), button);
gtk_widget_show_all(win);
{Test call to recordInstance.testProcedure to see that it outputs
'7' correctly}
recordInstance.testProcedure;
gtk_main;
end.
When I try to use Classes or Objects instead of an Advanced Record, I receive error messages of the kind
"<procedure variable type of procedure of object;CDecl>" to "<procedure variable type of procedure;CDecl>"
What ways are there of using a structured data type with a procedure to use as a C callback as in the example above (if any)?
class static methods are compatible with procedures. But they also have the disadvantage that they don't have a reference to the data of the object.
{$mode delphi}
type
myRecord=record
public
myInt: Integer;
class procedure testProcedure; cdecl;static;
end;
tproctype = procedure; cdecl;
class procedure myrecord.testProcedure; cdecl;static;
begin
end;
var x : tproctype;
y : myrecord;
begin
x:=y.testprocedure;
end.
compiles, but the usage is sterile, since if it maps to plain C, it doesn't have (implicit) OO properties.
This may prove difficult -- I'm using multiple CORBA interfaces on an object, so it looks somehow like this:
TBaseObject = class(TSuperBaseObject, IInterfaceA)
function Afunction; // implemented from IInterfaceA
end;
TOtherObject = class(TBaseObject, IInterfaceB);
function Bfunction; // implemented from IInterfaceB
end;
Now I have a function that takes a variant, and in case that variant is an object, it assumes that object to be a IInterfaceA object:
case var.vtype of
...
vtObject : begin
Something := (var.vObject as IInterfaceA).AFunction; (1)
end;
end;
Now once I run that code, and pass a TOtherObject to the function, in line (1) BFunction gets called with forced parameters!
Am I doing something wrong or is it a bug in the compiler? Also, any sane way to circumvent that without changing the class structure?
Full code for a EAccessViolation if anyone wants to try - http://pastebin.com/D7sDpDHx
Reported this as a bug to the FPC bugtracker - http://bugs.freepascal.org/view.php?id=20076
It turned out that FPC doesn't identify CORBA interfaces internally. To solve the problem one needs to identify them by himself:
type IInterfaceA = interface['interface_a']
function AFunction;
end;
Then the as keyword will work.
Not sure about FreePascal, but in Delphi you would use the supports function to query the interface.
var
IntfA : IInterfaceA;
IntfB : IInterfaceB;
begin
case var.vtype of
...
vtObject : begin
if supports(var.vObject,IInterfaceA,IntfA) then
Something := IntfA.AFunction
else if supports(var.vObject,IInterfaceB,IntfB) then
Something := IntfB.BFunction;
end;
end;
end;
So I come from the traditional game development that uses OOP principles and from what I've seen you can mimic this using LUA once you know what you are doing. In some of the code postings I found out how you can use the director class and create files that have a new() function etc.
What I'm looking for is a way to manage my weapons. I have a player and an opponent and I would prefer to have one weapon class, say weaponCanon. What I have done is:
-- private vars here
local power
local canonSprite
local whatever
local someFunction = function()
...
end
-- Private stuff here
local weaponCanon = {}
weaponCanon.fire = function(atX, atY)
...
end
weaponCanon.reset = function()
...
end
return weaponCanon
Then in my level code I simply do:
local weaponCanon = require("weaponCanon")
weaponCanon.fire(100, 100)
This works great and allows me to use a "private" and "public" mentality when coding up my weapons. The problem is that if I want the player and opponent to have a canon:
local playerWeapon = require("weaponCanon")
local opponentWeapon = require("weaponCanon")
This simply returns the same object instead of a new instance to that object. So I only get one weaponCanon at the opponentWeapon location. This is obviously now what I want/need.
Our game has many weapons in it and it would be nice to only have one version of each file with a setting telling us if its the opponents weapon or players weapon. The alternative is to copy each file and create a weaponPlayerCanon and a weaponOpponentCanon but I cringe at the thought of modifications to one file and having to change 2+ files every time.
How can I make it return an instance and what is the structure of the LUA file to do so?
Thanks or any and all help
-d
If later on you start needing inheritance (i.e. LaserCannon is a subclass of Weapon) you will probably need to use metatables more profoundly.
There are lots of libraries that will allow you to do "oop on top of Lua". You can see a very good list here:
http://lua-users.org/wiki/ObjectOrientedProgramming
I'm the author of middleclass. With my lib, you would have to do something like this:
local Weapon = class('Weapon')
function Weapon:initialize(a,b,c)
self.x,self.y,self.z = a,b,c
end
function Weapon:fire(x,y)
...
end
LaserCannon would be easy to implement - you just pass a second parameter to class:
local LaserCannon = class('LaserCannon', Weapon)
function LaserCannon:initialize(a,b,c,d)
self.w = d
Weapon.initialize(self, a,b,c) -- superclass' constructor
end
function LaserCannon:foo()
...
end
You could use it like this:
require 'middleclass' -- so you can use "class"
LaserCannon = require 'laser_cannon'
local playerWeapon = LaserCannon:new() -- a laser
local opponentWeapon = Weapon:new() -- a regular generic weapon
opponentWeapon:fire(100,200) -- typical use
playerWeapon:fire(100, 200) -- LaserCannon inherits fire from Weapon
playerWeapon:foo() -- LaserCannon-exclusive
This is with middleclass, which is the one I prefer, since I made it. Other libraries on the page I mentioned before offer similar features.
I guess you are trying to model a class with your source file. This means you should also have a function to create a new instance of that class unless you want them to share all their state.
Something along the lines of (untested):
local WeaponCannon = {}
WeaponCannon.__index = WeaponCannon
function WeaponCannon:new()
return setmetatable({}, self)
end
function WeaponCannon:fire(x, y)
-- Do something via the self reference and arguments (x, y)
end
return WeaponCannon
And in your calling code (also untested):
require('WeaponCannon')
local playerWeapon = WeaponCannon:new()
local opponentWeapon = WeaponCannon:new()
Although you create a new table for the weapon object, you don't create new variables. Any variables declared at the top of your module like that are essentially static variables (ie. variables shared by all instances of a class.) To create variables that are unique to that object you need to create them in the table, something like:
weaponCannon = {}
weaponCannon.power = 10
And anyway you only create an object once, you need a "constructor" function that creates the tables:
function new()
local weaponCannon = {}
weaponCannon.power = 10
end
Incidentally, two other things that aren't directly related to your answer but can be very useful modifications to your code. First off, using a colon instead of a period to call functions in a method will allow you to use the "self" keyword inside the method, something like:
function weaponCannon:fire()
--this is only a test
print(self.power)
end
then
local playerWeapon = require("weaponCanon")
playerWeapon:fire()
Second, you can actually use display objects as tables, rather than having to create an empty table and then sticking the display object into that empty table:
weaponCannon = display.newImage("cannon.png")
weaponCannon.power = 10
Note that you can't set the meta-table if you do this however. I find this approach looks more logical and prefer not to use meta-tables myself, but that's your call.
There are no objects here- you just have a bunch of global data. You really need to be making instances.
function NewWeapon(arg)
return {
fire = function(self, atX, atY)
print(self.var)
end,
var = arg,
}
end
NewWeapon(3):fire(1, 2)
NewWeapon(7):fire(3, 5)
I like ponzao's answer. Would however change it to:
local WeaponCannon = {}
function WeaponCannon:new()
local instance = {}
setmetatable(instance, {__index = WeaponCannon})
-- setup your new instance here
return instance
end
function WeaponCannon:fire(x, y)
-- Do something via the self reference and arguments (x, y)
end
return WeaponCannon
And in your calling code:
local WeaponCanon = require('WeaponCannon')
local playerWeapon = WeaponCannon:new()
local opponentWeapon = WeaponCannon:new()
What I've changed:
Created a local instance variable to allow for setup before returning it
More compact way of setting the metatable
Use a variable for the class when calling the code