When adding new properties to classes, I find myself typing the same things over and over in xcode:
add TYPE *NAME; (in .h interface)
add #property (nonatomic, retain) TYPE *NAME; (in .h)
add #synthesize NAME; (in .m)
add [NAME release]; (in .m dealloc)
(I'm in a non-garbage collected environment.)
How can I do this automatically?
That sounds about right. IIRC, the Objective-C 2.0 doc says you might be able to leave out step #1, but otherwise I don't know of any shortcuts.
You could probably write a user script to do so within Xcode. See http://www.mactech.com/articles/mactech/Vol.23/23.01/2301XCode/index.html.
According to the Developer Documentation in 64bit runtimes you can leave out step 1.
You could look at Andrew Pang's RMModelObject - I haven't used it, but it acts as a object base class that simplifies model creation.
I haven't used it, but here's some of what's highlighted in the readme:
no need to declare instance variables,
no need to write accessor methods,
free NSCopying protocol support (-copyWithZone:),
free NSCoding protocol support (-initWithCoder:, -encodeWithCoder:),
free -isEqual: and -hash` implementation,
no need to write -dealloc in most cases.
Here's another solution which I modified from
this article (also see the initial article)
The version in the blog was searching for variables outside of the variable declaration block and was matching method names too. I have done a crude fix to only search for variables before the first '}'. This will break if there are multiple interface declarations in the header file.
I set the output to "Replace Document Conents" and input as "Entire Document"
....
#!/usr/bin/python
thisfile = '''%%%{PBXFilePath}%%%'''
code = '''%%%{PBXAllText}%%%'''
selmark = '''%%%{PBXSelection}%%%'''
import re
if thisfile.endswith('.h'):
variableEnd = code.find('\n', code.find('}'))
properties = []
memre = re.compile('\s+(?:IBOutlet)?\s+([^\-+#].*? \*?.*?;)')
for match in memre.finditer(code[:variableEnd]):
member = match.group(1)
retain = member.find('*') != -1 and ', retain' or ''
property = '#property (nonatomic%s) %s' % (retain,member)
if code.find(property) == -1:
properties.append(property)
if properties:
print '%s\n\n%s%s%s%s' % (code[:variableEnd],selmark,'\n'.join(properties),selmark,code[variableEnd:])
elif thisfile.endswith('.m'):
headerfile = thisfile.replace('.m','.h')
properties = []
retains = []
propre = re.compile('#property\s\((.*?)\)\s.*?\s\*?(.*?);')
header = open(headerfile).read()
for match in propre.finditer(header):
if match.group(1).find('retain') != -1:
retains.append(match.group(2))
property = '#synthesize %s;' % match.group(2)
if code.find(property) == -1:
properties.append(property)
pindex = code.find('\n', code.find('#implementation'))
if properties and pindex != -1:
output = '%s\n\n%s%s%s' % (code[:pindex],selmark,'\n'.join(properties),selmark)
if retains:
dindex = code.find('\n', code.find('(void)dealloc'))
output += code[pindex:dindex]
retainsstr = '\n\t'.join(['[%s release];' % retain for retain in retains])
output += '\n\t%s' % retainsstr
pindex = dindex
output += code[pindex:]
print output
There is Kevin Callahan's Accessorizer. From the web page:
Accessorizer selects the appropriate
property specifiers based on ivar type
- and can also generate explicit accessors (1.0) automagically ... but
Accessorizer does much, much more ...
Related
Hash with typed keys…
use v6;
class Foo {}
my Hash[Foo, Foo] $MAP;
my $f1 = Foo.new;
my $f2 = Foo.new;
$MAP{$f1} = $f2;
produces the error:
Invocant of method 'ASSIGN-KEY' must be an object instance of type 'Hash[Foo,Foo]', not a type object of type 'Hash[Foo,Foo]'. Did you forget a '.new'?
I find it misleading; what's the real error and what do I have to write instead?
I already tried the % sigil for the hash variable, that doesn't work, either.
In the way you have defined it, $MAP is actually a role. You need to instantiate (actually, pun) it:
class Foo {}
my Hash[Foo, Foo] $MAP;
my $map = $MAP.new;
my $f1 = Foo.new;
my $f2 = Foo.new;
$map{$f1} = $f2;
say $map;
Dead giveaway here was that classes can't be parametrized, roles do.
Also:
say $MAP.DEFINITE; # False
say $map.DEFINITE; # True
But actually the error message was pretty informative, up to and including the suggestion to use .new, as I do here.
We can shorten it down to:
class Foo {}
my %map = Hash[Foo, Foo].new ;
%map{Foo.new} = Foo.new;
%map.say;
By doing the punning from the definition, we don't need the $MAP intermediate class.
TL;DR JJ's answer is right, but the explanation left me confused. I currently view the problem you showed as an autovivification error/bug and/or LTA error message.
say my Any $Any; # (Any)
say my Hash $Hash; # (Hash)
say my Hash[Int] $Hash-Int; # (Hash[Int])
$Any<a> = 42; # OK
$Hash<a> = 42; # OK
$Hash-Int.new<a> = 42; # OK
$Hash-Int<a> = 42; # must be an object instance, not a type object
Imo this is a bug or pretty close to one.
A bug/problem applies for arrays too in the same scenario:
say my Any $Any; # (Any)
say my Array $Array; # (Array)
say my Array[Int] $Array-Int; # (Array[Int])
$Any[42] = 42; # OK
$Array[42] = 42; # OK
$Array-Int.new[42] = 42; # OK
$Array-Int[42] = 42; # Type check failed ... expected Array[Int] but got Array
If it's best considered notabug, then perhaps the error message should be changed. While I agree with JJ that the error message is actually on point (when you understand how raku works and figure out what's going on), I think it's nevertheless an LTA error message if we don't change raku(do) to dwim.
On the gripping hand, it's not obvious to me how one could best improve the error message. And now we have this SO. (cf my point about that in Is the ... error message LTA? in a recent answer I wrote.)
Another solution
I already tried the % sigil for the hash variable, that doesn't work, either.
JJ has provided a solution that initializes with a value with an explicit .new. But that drops the constraint from the variable. To retain it:
class Foo {}
constant FooFoo = Hash[Foo:D,Foo:D];
my %foo is FooFoo;
%foo{Foo.new} = Foo.new;
Ideally the constant wouldn't be needed, and perhaps one day it won't, but I think trait parsing is limited.
-(void)updateCharacterStatsForArmor:(RKArmor *)armor withWeapons:(RKWeapon *)weapon withHealthEffect:(int)healtheffect
{
if (armor != nil){
self.character.health = self.character.health - self.character.armor.health + armor.health;
self.character.armor = armor;
}
else if (weapon != nil){
// The problematic line:
self.character.damage = self.character.damage - self.character.weapon.damage + weapon.damage;
self.character.weapon = weapon;
}
else if (healtheffect != 0){
self.character.health = self.character.health + healtheffect;
}
else {
self.character.health = self.character.health + self.character.armor.health;
self.character.damage = *(self.character.damage + self.character.weapon.damage);
}
}
#end
The line with the error is marked in the code snippet. The error says invalid operand to binary expression int int*.
Would It be best to restart the whole thing?
You probably defined one of the damage properties you're using as an int* instead of int. Check your character and weapon classes for that. I'd suspect self.character.damage.
If the line you indicated really is the problem, it looks like you've probably declared the damage property of the character class to return int * instead of int. It's easy to make that mistake because properties that point to objects are always pointers. int, however, is not an object type, so there's usually not need to store a pointer to one in a property.
The line you say is a problem is:
self.character.damage = self.character.damage - self.character.weapon.damage + weapon.damage;
But later on you have:
self.character.damage = *(self.character.damage + self.character.weapon.damage);
It looks like this second line is some kind of attempt to avoid a compiler error, but it doesn't seem to make a lot of sense. You'd only dereference the result of the addition if you were doing pointer arithmetic, but that doesn't make much sense for a property called damage.
To fix all this, take a look at your character class declaration. You'll probably see something like:
#property(...) int *damage;
Remove that * and make sure the attribute is assign, like this:
#property(assign) int damage;
Also, it's not clear how pirates are involved. Perhaps ye have been a mite hasty in makin' yer query? Arrr!
i found this code
gdk_rgba_parse ()
which should allow me to do something like
Gdk.RGBA.parse(#7F7F7F)
Error:
TypeError: unbound method parse() must be called with RGBA instance as first argument (got str instance instead)
using the RGBA color ( in percent, from 0 to 1 )
Docs:
https://developer.gnome.org/gdk3/stable/gdk3-RGBA-Colors.html#gdk-rgba-parse
http://www.crategus.com/books/cl-cffi-gtk/pages/gdk_fun_gdk-rgba-parse.html
But I'm kinda lost, i struggle to translate from C to PyGOBject and understanding the arguments of the function.. any help would be appreciated!
Since i didn't find the right solution, i made this converter:
def hex_to_rgba(value):
value = value.lstrip('#')
if len(value) == 3:
value = ''.join([v*2 for v in list(value)])
(r1,g1,b1,a1)=tuple(int(value[i:i+2], 16) for i in range(0, 6, 2))+(1,)
(r1,g1,b1,a1)=(r1/255.00000,g1/255.00000,b1/255.00000,a1)
return (r1,g1,b1,a1)
It works..
The function requires an instance of a GdkRGBA struct:
gboolean
gdk_rgba_parse (GdkRGBA *rgba,
const gchar *spec);
This translates to Python as a method on a Gdk.RGBA instance which mutates the structs contents:
color = Gdk.RGBA()
color.parse('#7F7F7F')
color.to_string() # 'rgb(127,127,127)'
It's not a very nice API for Python but every once in a while you have to deal with these kind of things with introspection based bindings. lazka's docs should be more helpful than the C ones:
http://lazka.github.io/pgi-docs/#Gdk-3.0/structs/RGBA.html#Gdk.RGBA.parse
Is it possible to define a MATLAB class such that the objects from this class can be called like any other function?
IOW, I'm asking whether one can write in MATLAB the equivalent of something like the following Python class:
# define the class FxnClass
class FxnClass(object):
def __init__(self, template):
self.template = template
def __call__(self, x, y, z):
print self.template % locals()
# create an instance of FxnClass
f = FxnClass('x is %(x)r; y is %(y)r; z is %(z)r')
# call the instance of FxnClass
f(3, 'two', False)
...
[OUTPUT]
x is 3; y is 'two'; z is False
Thanks!
I do not know, whether MATLAB directly supports what you want, but MATLAB does support first-class functions; closures might therefore provide a useable substitute, for instance:
function f = count_call(msg)
calls = 0;
function current_count()
disp(strcat(msg, num2str(calls)));
calls = calls + 1;
end
f = #current_count;
end
In this case, current_count closes over calls (and msg). That way you can express functions that depend on some internal state. You would use it this way:
g = count_call('number of calls: ') % returns a new function ("__init__")
g() % "__call__"
I will be interested to see if this is possible without simply creating a java method in Matlab. I know you can do the following
classdef ExampleObject
properties
test;
end
methods
function exampleObject = ExampleObject(inputTest)
exampleObject.test=inputTest;
end
function f(exampleObject,funcInput)
disp(funcInput+exampleObject.test);
end
end
end
>> e=ExampleObject(5);
>> f(e,10)
15
But as far as my knowledge goes, if you tried to override the call function you'd run into a conflict with Matlab's parenthetical subscript reference subsref. You can find a reference here showing how to overwrite that, and you might be able to get it to do what you want...but it doesn't seem like good form to do so. Not sure how Matlab would handle a call to an object (as opposed to a function) without it getting confused with this.
One way is to override the feval function for your class:
classdef FxnClass < handle
properties
template
end
methods
function obj = FxnClass(t)
obj.template = t;
end
function out = feval(obj, varargin)
out = sprintf(obj.template, varargin{:});
end
end
end
This would be used as:
>> f = FxnClass('x = %f, y = %s, z = %d');
>> feval(f, 3,'two',false)
ans =
x = 3.000000, y = two, z = 0
Now if you want to provide additional syntactic sugar, you could redefine the subsref function for your class as #Salain suggested. Add the following to the previous class definition:
classdef FxnClass < handle
...
methods
function out = subsref(obj, S)
switch S(1).type
case '.'
% call builtin subsref, so we dont break the dot notation
out = builtin('subsref', obj, S);
case '()'
out = feval(obj, S.subs{:});
case '{}'
error('Not a supported subscripted reference');
end
end
end
end
Now you could simply write:
>> f = FxnClass('x = %f, y = %s, z = %d');
>> f(3,'two',false)
ans =
x = 3.000000, y = two, z = 0
Personally I don't particularly like overriding the subsref or subsasgn functions. They are used for too many cases, and its sometimes hard to get them write. For example all the following will eventually call the subsref method with different input:
f(..)
f.template
f.template(..)
f(..).template
f(..).template(..)
There is also the case of the end keyword which could appear in indexing, so you might have to also override it as well in some cases. Not to mention that objects can also be concatenated into arrays, which makes things even more complicated:
>> ff = [f,f];
>> ff(1) % not what you expect!
That said, I think #Frank's suggestion to use nested functions with closures is more elegant in this case:
function f = FxnClass(t)
f = #call;
function out = call(varargin)
out = sprintf(t, varargin{:});
end
end
which is called as before:
>> f = FxnClass('x = %f, y = %s, z = %d');
>> f(3, 'two', false)
If you mean that you want a class to hold a method which you use like a normal function (eg. defined in an m-file), then yes, Matlab does support static methods.
A static method runs independently of any instances of that class, in fact, you don't even need to instantiate a class to use its static methods.
Matlab does not support static fields, however, so you would have to instantiate such a class first, and then set its fields before using the functions (which presumably make use of these fields, since you are asking this question).
Given the limitation with static members, you might be better off with closures, as described by Frank.
I am trying to make MATLAB a bit more usable than it is (for me), and one of the things which I always wanted to fix is a better class constructor. I want to have the following interface:
MyClass.new(some_args).method1;
# instead of classical:
obj = MyClass(some_args);
obj.method1;
I can easily achieve this by defining a static method new:
classdef MyClass
methods
function obj = MyClass(varargin); end
function method1(obj,varargin); end
end
methods (Static)
function obj = new(varargin); obj = MyClass(varargin{:}); end
end
end
But this requires adding such method to all classes, and therefore it is not very elegant/convenient. I thought that I could go around it by defining a common class with the following constructor
classdef CommonClass
methods (Static)
function obj = new(varargin)
# getting name of the current file (Object), i.e. basename(__FILE__)
try clear E; E; catch E, [s, s] = fileparts(E.stack(1).file); end;
# creating object with name $s
obj = eval([s '(varargin{:})']);
end
end
end
classdef MyClass < CommonClass
end
However, this doesn't work because MATLAB calls new() from Object.m, and therefore I get instance of Object instead of MyClass.
Any ideas how I can improve it?
EDIT1:
I would like it to work also for classes created inside other ones:
classdef MyAnotherClass < CommonClass
methods
function obj = MyAnotherClass
child = MyClass.new;
end
end
end
>> MyAnotherClass.new
Personally, I don't see the problem with calling the constructor as is, but if you do want to have it called via new, the getStaticCallingClassName below might be of use to you.
Here's how you'd use it:
classdef CommonClass
methods (Static)
function obj = new(varargin)
%# find out which class we have to create
className = getStaticCallingClassName;
constructor = str2func(sprintf('#%s'className));
%# creating object with name $s
obj = constructor(varargin{:});
end
end
end
classdef MyClass < CommonClass
end
With this, you can call
obj = MyClass.new(input,arguments);
And here's getStaticCallingClassName:
function className = getStaticCallingClassName
%GETSTATICCALLINGCLASSNAME finds the classname used when invoking an (inherited) static method.
%
% SYNOPSIS: className = getStaticCallingClassName
%
% INPUT none
%
% OUTPUT className: name of class that was used to invoke an (inherited) static method
%
% EXAMPLE
%
% Assume you define a static method in a superclass
% classdef super < handle
% methods (Static)
% doSomething
% % do something here
% end
% end
% end
%
% Also, you define two subclasses
% classdef sub1 < super
% end
%
% classdef sub2 < super
% end
%
% Both subclasses inherit the static method. However, you may be
% interested in knowing which subclass was used when calling the static
% method. If you call the subclass programmatically, you can easily pass
% the name of the subclass as an input argument, but you may want to be
% able to call the method from command line without any input and still
% know the class name.
% getStaticCallingClassName solves this problem. Calling it in the above
% static method 'doSomething', it returns 'sub1' if the static method was
% invoked as sub1.doSomething. It also works if you create an instance of
% the subclass first, and then invoke the static method from the object
% (e.g. sc = sub1; sc.doSomething returns 'sub1' if .doSomething calls
% getStaticCallingClassName)
%
% NOTE: getStaticCallingClassName reads the last workspace command from
% history. This is an undocumented feature. Thus,
% getStaticCallingClassName may not work in future releases.
%
% created with MATLAB ver.: 7.9.0.3470 (R2009b) on Mac OS X Version: 10.5.7 Build: 9J61
%
% created by: Jonas Dorn
% DATE: 16-Jun-2009
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% get the last entry of the command line from the command history
javaHistory=com.mathworks.mlservices.MLCommandHistoryServices.getSessionHistory;
lastCommand = javaHistory(end).toCharArray';%'# SO formatting
% find string before the last dot.
tmp = regexp(lastCommand,'(?:=|\.)?(\w+)\.\w+\(?(?:.*)[;,]*\s*$','tokens');
try
className = tmp{1}{1};
catch me
className = [];
end
% if you assign an object, and then call the static method from the
% instance, the above regexp returns the variable name. We can get the
% className through getting the class of xx.empty.
if ~isempty(className)
className = evalin('base',sprintf('class(%s.empty);',className));
end
I could be missing something, but what's wrong with
method1(MyClass(some_args))
? (I use this pattern all the time).