[email protected] writes:
prog18-2.m: In function 'main':
prog18-2.m:58: warning: 'Fraction' may not respond to '+new'
prog18-2.m:58: warning: (Messages without a matching method signature prog18-2.m:58: warning: will be assumed to return 'id' and accept prog18-2.m:58: warning: '...' as arguments.)
prog18-2.m:71: warning: 'Fraction' may not respond to '-free'
You should use NSObject from Foundation, and dealloc instead of free.
Using Object poses problems; On Linux, gcc Object class is almost empty,
and doesn't have alloc/dealloc or the older new/free. On MacOSX, Object
is not defined for Objective-C version 2 (if __OBJC2__ is defined), which
is the case by default.
A good way to deal with this problem, would be to define your own root
class, that would inherit from NSObject or Object depending on the
version of the language and where it's compiled on.
----(MyObject.h)----------
#ifdef …
…
#endif
@interface MyObject
…
@end
--------------------------
---(Fraction.m)-----------
#import "MyObject.h"
@interface Fraction:MyObject
…
@end
--------------------------
This way, you would hide the problem in a single class, MyObject, to
adapt to the various platforms.
Should I use .m or .c for such programs? Am I using a correct compilation command?
.m for Objective-C sources.
----(Fraction.m)------------------------------------------------------------ #import <stdio.h>
#import <Foundation/Foundation.h>
//------ @interface section ---------
@interface Fraction:NSObject
{
int numerator;
int denominator;
}
-(void)free;
-(void) set_numerator: (int) n;
-(void) set_denominator: (int) d;
-(void) print;
@end
// ----- @implementation section -------
@implementation Fraction;
-(void)free{[self dealloc];}
// getters
-(int) numerator
{
return numerator;
}
-(int) denominator
{
return denominator;
}
//setters
-(void) set_numerator: (int) num
{
numerator = num;
}
-(void) set_denominator: (int) denom
{
denominator = denom;
}
//other
-(void) print
{
printf("The value of the fraction is %i/%i\n", numerator, denominator);
}
@end
//-------- program section -----------
int main(void)
{
Fraction* my_fract;
my_fract = [Fraction new];
[my_fract set_numerator: 1];
[my_fract set_denominator: 3];
printf("The numerator is %i, and teh denominator is %i\n", [my_fract numerator], [my_fract denominator]);
[my_fract print];
[my_fract dealloc]; //frees the memory that was used by Fraction object
return 0;
}
----(Makefile)------------------------------------------------------------ all:spl-example fraction
.PHONY::run get-dependencies
get-dependencies:
cd /usr/local/src/ ; git clone
[email protected]:cs50/spl.git
cd /usr/local/src/spl ; make && make install
run:spl-example
CLASSPATH=/usr/local/lib/spl.jar ./spl-example
LIBS=-lcs -lm -lobjc
CFLAGS=-g3 -O0
spl-example.o:spl-example.m
Fraction.o:Fraction.m
fraction:Fraction.o
gcc $(CFLAGS) $^ -o $@ $(LIBS)
spl-example:spl-example.o
gcc $(CFLAGS) $^ -o $@ $(LIBS)
clean:
-rm spl-example fraction
-rm -rf *.dSYM *.o
--------------------------------------------------------------------------------
[pjb@larissa :0.0 spl-example]$ make
cc -g3 -O0 -c -o spl-example.o spl-example.m
gcc -g3 -O0 spl-example.o -o spl-example -lcs -lm -lobjc
cc -g3 -O0 -c -o Fraction.o Fraction.m
gcc -g3 -O0 Fraction.o -o fraction -lcs -lm -lobjc
[pjb@larissa :0.0 spl-example]$ ./fraction
The numerator is 1, and teh denominator is 3
The value of the fraction is 1/3
[pjb@larissa :0.0 spl-example]$
Some advices:
- in general, you should separate the modules implementing the core
algorithms, from the modules implementing the user interface. This
means, don't do I/O in the classes that model the domain or do
computations or storage.
- consider having immutable classes. Instead of having methods to
modify the state of the object, initialize the instance with all the
data, and then don't modify it. This is particularly true in a class
like Fraction, since it represent a number and that should be
immutable.
- similarly, if you want to implement parts of your code in C, and parts
in Objective-C, I would advise to modularize it very clearly, by
separating the C code into a purely C module, which can then be used
from the Objective-C classes. This allows to re-use the C modules
from other languages (C++, Lisp, etc).
# This is a shell archive. Save it in a file, remove anything before
# this line, and then unpack it by entering "sh file". Note, it may
# create directories; files and directories will be owned by you and
# have default permissions.
#
# This archive contains:
#
# fr/Makefile
# fr/MyFraction.h
# fr/MyFraction.m
# fr/MyFractionView.h
# fr/MyFractionView.m
# fr/MyObject.h
# fr/MyObject.m
# fr/fraction.c
# fr/fraction.h
# fr/log.txt
# fr/main.m
#
echo x - fr/Makefile
sed 's/^X//' >fr/Makefile << 'END-of-fr/Makefile'
Xall:run
X
XOBJECTS=main.o MyObject.o MyFractionView.o MyFraction.o fraction.o
XLIBS=-lcs -lobjc -lm
XCFLAGS=-g3 -O0 -Werror -Wall
X
Xfraction.o:fraction.c fraction.h
XMyFraction.o:MyFraction.m MyFraction.h MyObject.h XMyFractionView.o:MyFractionView.m MyFractionView.h MyFraction.h MyObject.h XMyObject.o:MyObject.m MyObject.h
Xmain.o:main.m MyFractionView.h MyFraction.h
X
Xfraction:$(OBJECTS)
X gcc $(CFLAGS) -o $@ $^ $(LIBS)
X
Xclean:
X -rm *.o fraction
X
Xrun:fraction
X ./fraction
END-of-fr/Makefile
echo x - fr/MyFraction.h
sed 's/^X//' >fr/MyFraction.h << 'END-of-fr/MyFraction.h'
X#import "MyObject.h"
X#import "fraction.h"
X
X@interface MyFraction:MyObject
X{
X struct fraction* fraction;
X}
X
X-(id)initWithNumerator:(int)num andDenominator:(int)den;
X-(int)numerator;
X-(int)denominator;
X
X@end
X
END-of-fr/MyFraction.h
echo x - fr/MyFraction.m
sed 's/^X//' >fr/MyFraction.m << 'END-of-fr/MyFraction.m'
X#import "MyFraction.h"
X
X@implementation MyFraction
X
X-(id)initWithNumerator:(int)num andDenominator:(int)den{
X if((self=[super init])){
X fraction=fraction_new(num,den);
X }
X return self;
X}
X
X-(int)numerator{
X return fraction_num(fraction);
X}
X
X-(int)denominator{
X return fraction_den(fraction);
X}
X
X@end
X
END-of-fr/MyFraction.m
echo x - fr/MyFractionView.h
sed 's/^X//' >fr/MyFractionView.h << 'END-of-fr/MyFractionView.h'
X#import <stdio.h>
X#import "MyFraction.h"
X
X@interface MyFractionView:MyObject
X{
X MyFraction* fraction;
X}
X
X-(id)initWithFraction:(MyFraction*)aFraction; X-(void)displayOnStream:(FILE*)output;
X
X@end
X
END-of-fr/MyFractionView.h
echo x - fr/MyFractionView.m
sed 's/^X//' >fr/MyFractionView.m << 'END-of-fr/MyFractionView.m'
X#import "MyFractionView.h"
X
X@implementation MyFractionView
X
X-(id)initWithFraction:(MyFraction*)aFraction {
X if((self=[super init])){
X fraction=aFraction;
X }
X return self;
X}
X
X-(void)displayOnStream:(FILE*)output {
X fprintf(output,"%i/%i",[fraction numerator],[fraction denominator]);
X}
X
X@end
X
END-of-fr/MyFractionView.m
echo x - fr/MyObject.h
sed 's/^X//' >fr/MyObject.h << 'END-of-fr/MyObject.h'
X/* -*- mode:objc -*- */
X#import <Foundation/Foundation.h>
X@interface MyObject:NSObject
X-(void)free;
X@end
X
END-of-fr/MyObject.h
echo x - fr/MyObject.m
sed 's/^X//' >fr/MyObject.m << 'END-of-fr/MyObject.m'
X#import "MyObject.h"
X
X@implementation MyObject
X-(void)free{
X [self dealloc];
X}
X@end
END-of-fr/MyObject.m
echo x - fr/fraction.c
sed 's/^X//' >fr/fraction.c << 'END-of-fr/fraction.c'
X#include "fraction.h"
X#include <libc.h>
X
Xtypedef struct fraction {
X int num;
X int den;
X} fraction;
X
Xfraction* fraction_new(int num,int den){
X if(den==0){
X return NULL;
X }
X fraction* fr=malloc(sizeof(*fr));
X if(fr){
X fr->num=num;
X fr->den=den;
X }
X return fr;
X}
X
X
X
Xint fraction_num(fraction* fr){
X if(fr){
X return fr->num;
X }else{
X return 0;
X }
X}
X
Xint fraction_den(fraction* fr){
X if(fr){
X return fr->den;
X }else{
X return 1;
X }
X}
X
Xvoid fraction_free(fraction* fr){
X if(fr){
X free(fr);
X }
X}
X
END-of-fr/fraction.c
echo x - fr/fraction.h
sed 's/^X//' >fr/fraction.h << 'END-of-fr/fraction.h'
X#ifndef __fraction__
X#define __fraction__
X
Xextern struct fraction* fraction_new(int num,int den);
Xextern int fraction_num(struct fraction* fr);
Xextern int fraction_den(struct fraction* fr);
Xextern void fraction_free(struct fraction* fr);
X
X#endif
END-of-fr/fraction.h
echo x - fr/log.txt
sed 's/^X//' >fr/log.txt << 'END-of-fr/log.txt'
X-*- mode: compilation; default-directory: "~/src/spl-example/fr/" -*- XCompilation started at Wed Nov 11 20:59:45
X
Xmake -k clean all
Xrm *.o fraction
Xcc -g3 -O0 -Werror -Wall -c -o main.o main.m
Xcc -g3 -O0 -Werror -Wall -c -o MyObject.o MyObject.m
Xcc -g3 -O0 -Werror -Wall -c -o MyFractionView.o MyFractionView.m
Xcc -g3 -O0 -Werror -Wall -c -o MyFraction.o MyFraction.m
Xcc -g3 -O0 -Werror -Wall -c -o fraction.o fraction.c
Xgcc -g3 -O0 -Werror -Wall -o fraction main.o MyObject.o MyFractionView.o MyFraction.o fraction.o -lcs -lobjc -lm
X./fraction
XThe numerator is 1, and the denominator is 3
XThe value of the fraction is 1/3
X
XCompilation finished at Wed Nov 11 20:59:46
END-of-fr/log.txt
echo x - fr/main.m
sed 's/^X//' >fr/main.m << 'END-of-fr/main.m'
X#import "MyFraction.h"
X#import "MyFractionView.h"
X
Xint main(int argc,char** argv){
X MyFraction* fraction=[[MyFraction alloc]initWithNumerator:1
X andDenominator:3];
X MyFractionView* view=[[MyFractionView alloc]initWithFraction:fraction];
X
X printf("The numerator is %i, and the denominator is %i\n",
X [fraction numerator], [fraction denominator]);
X printf("The value of the fraction is ");
X [view displayOnStream:stdout];
X printf("\n");
X return 0;
X}
END-of-fr/main.m
exit
--
__Pascal Bourguignon__
http://www.informatimago.com/
“The factory of the future will have only two employees, a man and a
dog. The man will be there to feed the dog. The dog will be there to
keep the man from touching the equipment.” -- Carl Bass CEO Autodesk
--- SoupGate-Win32 v1.05
* Origin: fsxNet Usenet Gateway (21:1/5)