I have a doubt in implementing oops concept in objective-c.Is Pholyorphism possible in objective-c. How to implement polymorphism in objective-c.please explain with example?
Every method, including class methods, is dynamic in Objective-C.
One very basic approach would be:
Declare the base interface:
#interface MONConstantColor : NSObject
- (UIColor *)color;
#end
Define the base implementation:
#implementation MONConstantColor
- (UIColor *)color { return /* ...do/ret something appropriate */; }
#end
Then create some variations:
#interface MONRedColor : MONConstantColor
#end
#implementation MONRedColor
- (UIColor *)color { return [UIColor redColor]; }
#end
#interface MONYellowColor : MONConstantColor
#end
#implementation MONYellowColor
- (UIColor *)color { return [UIColor yellowColor]; }
#end
- (HomeWorkResult *)homeWorkResultFromHomeWorkTask:(HomeWorkTask *)task
{
if (!self.lazy) {
return [self HW_performHomeWorkTask:task];
}
StackOverflowPost *post = [StackOverflow postHomeWorkTask:task];
for (id user in post.responders) {
// Here is the pholyorphism[sic].
// First, test to see if a stack overflow user is able to do home work tasks.
if ([user respondsToSelector:#selector(homeWorkResultFromHomeWorkTask:)]) {
// Next, have the user do the home work task.
HomeWorkResult *result = [user homeWorkResultFromHomeWorkTask:task];
// If there is a result, return that result.
if (result) {
return result;
}
}
}
// Finally, if no stack overflow user does home work tasks or if there was no
// result perform the task yourself.
return [self HW_performHomeWorkTask:task];
}
The word polymorphism means having many forms
Objective-C polymorphism means that a call to a member function will cause a different function to be executed depending on the type of object that invokes the function.
Consider the example, we have a class Shape that provides the basic interface for all the shapes. Square and Rectangle are derived from the base class Shape.
We have the method printArea that is going to show about the OOP feature polymorphism.
#import <Foundation/Foundation.h>
#interface Shape : NSObject
{
CGFloat area;
}
- (void)printArea;
- (void)calculateArea;
#end
#implementation Shape
- (void)printArea{
NSLog(#"The area is %f", area);
}
- (void)calculateArea{
}
#end
#interface Square : Shape
{
CGFloat length;
}
- (id)initWithSide:(CGFloat)side;
- (void)calculateArea;
#end
#implementation Square
- (id)initWithSide:(CGFloat)side{
length = side;
return self;
}
- (void)calculateArea{
area = length * length;
}
- (void)printArea{
NSLog(#"The area of square is %f", area);
}
#end
#interface Rectangle : Shape
{
CGFloat length;
CGFloat breadth;
}
- (id)initWithLength:(CGFloat)rLength andBreadth:(CGFloat)rBreadth;
#end
#implementation Rectangle
- (id)initWithLength:(CGFloat)rLength andBreadth:(CGFloat)rBreadth{
length = rLength;
breadth = rBreadth;
return self;
}
- (void)calculateArea{
area = length * breadth;
}
#end
int main(int argc, const char * argv[])
{
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
Shape *square = [[Square alloc]initWithSide:10.0];
[square calculateArea];
[square printArea];
Shape *rect = [[Rectangle alloc]
initWithLength:10.0 andBreadth:5.0];
[rect calculateArea];
[rect printArea];
[pool drain];
return 0;
}
use this link as refernce
http://www.tutorialspoint.com/objective_c/objective_c_polymorphism.htm
Related
I need access address of property but have problem. example code is
#interface Rectangle : NSObject
{
SDL_Rect wall;
SDL_Rect ground;
}
#property SDL_Rect wall;
#property SDL_Rect ground;
#end
#implementation Rectangle
#synthesize x;
#synthesize y;
#end
#interface Graphics : NSObject
{
int w;
int h;
}
-(void) drawSurface
#end
#implementation Graphics
-(void) drawSurface
{
Rectangle *rect = [[Rectangle alloc] init];
SDL_BlitSurface(camera, NULL, background, &rect.wall);
}
#end
&rect.x is Address of property expression requested
As the comments suggest, you cannot take the address of a property. A property is really just a promise that the object in question provides accessors for some value. The value itself may or may not even exist in an instance variable. For example, the getter for a property called fullName might generate the required value on the fly by concatenating the values of firstName and lastName properties.
Since you need to pass the address of a SDL_Rect into SDL_BlitSurface(), you could first copy the necessary property into a local variable, and then pass the address of that variable:
Rectangle *rect = [[Rectangle alloc] init];
SDL_Rect wall = rect.wall;
SDL_BlitSurface(camera, NULL, background, &wall);
If you need to preserve the value left in wall after the call to SDL_BlitSurface(), copy it back again after the call:
rect.wall = wall;
I had a similar situation with subclasses needing to access a CGAffineTransform defined in the parent class. The answer came from #orpheist's answer to this question: Get the address of an Objective-c property (which is a C struct). It does involve adding a method to your Rectangle class.
#interface Rectangle : NSObject
{
NSRect wall;
NSRect ground;
}
#property NSRect wall;
#property NSRect ground;
#end
#implementation Rectangle
#synthesize wall = _wall; //x;
#synthesize ground = _ground; //y;
- (const NSRect *) addressOfWall {
return &_wall;
}
- (const NSRect *) addressOfGround {
return &_ground;
}
+(instancetype)standardRectangle
{
Rectangle *newInstance = [[self alloc] init];
newInstance.wall = NSMakeRect(0,0, 300, 100);
newInstance.ground = NSMakeRect(0 ,0, 300, 450);
return newInstance;
}
#end
Now you can use, for instance, addressOfWall thus:
- (void)testWall
{
Rectangle *rect = [Rectangle standardRectangle];
XCTAssertEqual(100, [rect addressOfWall]->size.height);
}
Address of property expression requested that means:
#preperty (nonatomic,copy) NSString *name;
if you want to get the address of self.name. You cannot write the code like this:
NSLog (#"%p",&(self.name));
Because in fact,self.name is getter method, like this:
- (NSString *)name {
return _name;
}
so you cannot get address of method.
Let's say I want to create a bunch of different types of Spaceships. I want to setup a base spaceship class that I can use to create other spaceships with minor differences.
My base class looks like this.
// BaseSpaceship.h
#interface SpaceshipNode : SKSpriteNode
#property NSColor color;
#property CGFloat engineThrust;
+ (id)baseSpaceshipWithImageNamed:(NSString *)name;
#end
// BaseSpaceship.m
#implementation BaseSpaceship
+ (id)baseSpaceshipWithImageNamed:(NSString *)name {
BaseSpaceship *ship = [BaseSpaceship spriteNodeWithImageNamed:name];
ship.color = [NSColor redColor];
ship.engineThrust = 2.0;
return ship;
}
#end
I can create a ship in MyScene.m like this just fine.
BaseSpaceship *baseClass = [BaseSpaceship baseSpaceshipWithImageNamed:#"BaseShip"];
However, I'm not sure how to create a subclass of BaseSpaceship, for example, DestroyerSpaceship. I'm not sure if I should be using static methods or not. The examples I've seen online use static methods to instantiate SKSpriteNodes. This is what I came up with, but it's wrong.
// DestroyerSpaceship.h
#interface DestroyerSpaceship : BaseSpaceship
#property CGFloat missileThrust;
- (id)makeDestroyerSpaceship;
#end
// DestroyerSpaceship.m
#implementation DestroyerSpaceship
- (id)makeDestroyerSpaceship{
DestroyerSpaceship *ship = [DestroyerSpaceship baseSpaceshipWithImageNamed:#"DestroyerShip"];
ship.engineThrust = 2.0;
// ship doesn't have missileThrust, program crashes
ship.missileThrust = 3.0;
return ship;
}
#end
Ultimately, I want to be able to do something like this.
DestroyerSpaceship* a = [DestroyerSpaceship makeDestroyerSpaceship];
EvilSpaceship* b = [EvilSpaceship makeEvilSpaceship];
NiceSpaceship* c = [NiceSpaceship makeNiceSpaceship];
And have them all inherit basic properties and methods from BaseSpaceship.
The answer is less complex than you think. Well, the code might be a bit more complex, but once you have the structure it is most flexible. Creating the different types of spaceships will also be a lot more readable.
You can override the initializer method in the subclass. As a sidenote, use (instancetype) instead of (id) (source: instancetype # NSHipster).
As you are adding custom body sprites to the object, I would opt to subclass SKNode instead of SKSpriteNode (so #interface SpaceshipNode : SKNode instead of #interface SpaceshipNode : SKSpriteNode).
#interface SpaceshipNode : SKNode
#property SKColor * color; // Use SKColor instead of NSColor
#property CGFloat engineThrust;
#end
// ...
#implementation SpaceshipNode
- (instancetype) init {
if (self == [super init]) {
NSLog(#"A new SpaceshipNode was just init'ed.");
// set some default initial values here that all brand-new SpaceshipNodes will inherit
// perhaps create and add a basic body sprite
// SKSpriteNode * body = ...;
// [self addChild:body];
// set thrust
self.engineThrust = 2.0;
}
return self;
}
Then you can subclass and create a new type of spaceship. Awesome!
#interface DestroyerSpaceship : SpaceshipNode
#property CGFloat missileThrust;
#end
#implementation DestroyerSpaceship
- (instancetype) init {
// note that [super init] will call the SpaceshipNode's init method
if (self = [super init]) {
NSLog(#"A new DestroyerSpaceship was just init'ed.");
// add a body sprite
// SKSpriteNode * body = ...;
// [self addChild:body];
// a Destroyer is much faster than your average spaceship
self.engineThrust = 10.0;
// set class specific variables
self.missileThrust = 5.f;
}
return self;
}
Now, you can just call:
SpaceshipNode * newSpaceShip = [SpaceshipNode new]; // short for [[SpaceshipNode alloc] init];
DestroyerSpaceship * newDestroyer = [DestroyerSpaceship new];
These two lines will log the following. The last two lines are caused by the Destroyer, which first calls the SpaceshipNode init, and then the Destroyer-specific init method.
A new SpaceshipNode was just init'ed.
A new SpaceshipNode was just init'ed.
A new DestroyerSpaceship was just init'ed.
And you can even use it like this:
SpaceshipNode * newUnidentifiedVessel = [DestroyerSpaceship new];
if ([newUnidentifiedVessel isKindOfClass:[DestroyerSpaceship class]]) {
NSLog(#"We are under attack! Route power to shields!");
}
- (instancetype)makeDestroyerSpaceship{
if (self = [super baseSpaceshipWithImageNamed:#"DestroyerShip"]) {
self.engineThrust = 2.0;
self.missileThrust = 3.0;
}
return self;
}
I have been struggling along with an online objective-c class for a few weeks now. I'm feeling very stupid..
My latest assignment is to write a program that demonstrates a class named Circle by asking the user for the circle's radius, creating a Circle object, and then reporting the circle's area, diameter, and circumference.
We should have the following member variables:
radius: a double
pi: a double initialized to 3.14159
and the following member functions:
setRadius - a mutator function for the radius variable
getRadius - an accessor function for the radius variable
getArea - returns the area of the circle, which is calculated as: area = pi * radius * radius
getDiameter - returns the diameter of the circle, which is calculated as: diameter = radius * 2
getCircumference - returns the circumference of the circle, which is calculated as: circumference = 2 * pi * radius
The member variables of the class should be set as private.
Here is my program so far:
Main:
int main(int argc, const char * argv[])
{
#autoreleasepool {
int radius;
NSLog(#"Enter the circles radius:");
scanf ("%d", &radius);
}
return 0;
}
Interface:
#import <Foundation/Foundation.h>
//circle class
#interface circle : NSObject
{ #private
-(double) radius;
-(double) pi;
}
#property int setRadius, getRadius;
-(double) getArea;
-(double) getDiameter;
-(double) getCircumcerence;
#end
Implementation:
#import "circle.h"
#implementation circle
#synthesize setRadius, getRadius;
-(double) pi
{
pi = 3.14159;
}
-(double) getArea
{
pi * radius * radius;
}
-(double) getDiameter
{
radius * 2;
}
-(double) getCircumcerence
{
2 * pi * radius;
}
#end
As you can see, I haven't gotten very far. I am confused as how to simply utilize my methods in my main, and am sure I have already made mistakes.
Any advice is appreciated! I really need help, and am short on time.
Also, this may be far-fetched but if anyone could maybe skype with me and help me through it?
Thanks!
As a starting point, you should set up your .h to something more like this:
#interface Circle : NSObject
#property double radius;
#property (readonly) double area;
#property (readonly) double diameter;
#property (readonly) double circumference;
#property (readonly) double pi;
-(id)initWithRadius:(double)r;
+(instancetype)circleWithRadius:(double)r;
#end
This will set up a setter and getter for radius as well as getters for area, diameter, and circumference. It also sets up an init and factory method for your circle which takes a double for the radius.
I will come back and edit in some modifications you need to make to your .m as well as your main file in order to make this work. As a note, at a minimum we'll override the getters for the 3 readonly properties. This will prevent the compiler from creating ivars (instance variables) for these properties (because we can just calculate and return the number we calculation when we call it).
In your .m:
#import Circle.h
#implementation Circle
-(id)initWithRadius:(double)r
{
self = [super init];
if(self) {
self.radius = r;
}
return self;
}
+(instancetype)circleWithRadius:(double)r
{
return [[Circle alloc] initWithRadius:r];
}
-(void)setRadius:(double)r //This method is automatically created by #property
{ //include any verification logic (make sure r>0 etc), then...
self.radius = r;
}
//we don't really need to override the radius getter
-(double)pi
{
return 3.14159; //or however much accuracy you want
}
-(double)area
{
return (self.pi * self.radius * self.radius);
}
-(double)diameter
{
return (2.0 * self.radius);
}
-(double)circumference
{
return (self.diameter * self.pi);
}
In main, you use this Circle class in just the same way you use any other object in Objective-C (think about NSString, NSArray, etc).
int main(int argc, const char * argv[])
{
#autoreleasepool {
double radius;
NSLog(#"Enter the circles radius:");
scanf ("%lf", &radius);
Circle *myCircle = [Circle circleWithRadius:radius]; //the factory method we set up
NSLog(#"myCircle radius: %lf", myCircle.radius);
NSLog(#"myCircle area: %lf", myCircle.area);
NSLog(#"myCircle diameter: %lf", myCircle.diameter);
NSLog(#"myCircle circumference: %lf", myCircle.circumference);
}
return 0;
}
There are of course many ways to set this up. I can remember being confused when starting out, below is an alternative example to give you something else to look at.
It is not intended to be fancy but just bare-bones so that you can see a minimal setup of the class with an initializer.
Note that the only value initialized is the const pi, of course, the radius can be initialized there as well, as nhgrif's example shows quite nicely.
Hope this helps!
// Circle.h
#import <Foundation/Foundation.h>
#interface Circle : NSObject
{
double radius;
double pi;
}
#property double radius, pi;
-(double) getArea;
-(double) getDiameter;
-(double) getCircumference;
#end
And then the implementation:
// Circle.m
#import "Circle.h"
#implementation Circle
#synthesize radius, pi;
// Initialize with const pi:
- (id)init {
self = [super init];
if (self) {
pi = 3.14159;
NSLog(#"Circle created.");
}
return self;
}
-(double) getArea {
return pi*radius*radius;
}
-(double) getDiameter {
return 2*radius;
}
-(double) getCircumference {
return 2*pi*radius;
}
#end
And then for main:
// main.m
#import <Foundation/Foundation.h>
#import "Circle.h"
int main(int argc, const char * argv[])
{
#autoreleasepool {
Circle *aCircle = [[Circle alloc] init];
// Use an arbitrary value:
[aCircle setRadius:2];
NSLog(#"Area = %f",[aCircle getArea]);
NSLog(#"Circumference = %f",[aCircle getCircumference]);
NSLog(#"Diameter = %f",[aCircle getDiameter]);
NSLog(#"Check pi = %f",[aCircle pi]);
}
return 0;
}
I try to understand how to work simple init funcion and I don't know where I have made a mistake. Can somebody assist?
Rectangle.h
#interface Rectangle : NSObject
{
int width;
int height;
}
-(id)initObject;
#end
Rectangle.m
#implementation Rectangle
-(id)initObject{
if (self = [super init]) {
height = 5;
width = 7;
}
return self;
}
#end
And in ViewController.h i import Rectangle.h, declare *rect object and in .m i execute(? run?) initObject.
ViewController.h
#import <UIKit/UIKit.h>
#import "Rectangle.h"
#interface ViewController : UIViewController
{
Rectangle *rect;
}
#end
ViewController.m
-(void)viewDidLoad
{
rect = [[Rectangle alloc] initObject];
NSLog(#"%#", rect);
[super viewDidLoad];
}
initObject return me:
2011-11-21 09:43:02.625 initializers[43693:f803] <Rectangle: 0x6ab1660>
The only problem with your code that I can see is you called your initializer -initObject for no good reason. It's not taking any parameters at all, so you really should just call it -init like every other parameterless initializer in the system.
As for the log output, I imagine your confusion lies in the fact that it says <Rectangle: 0x6ab1660>. This is perfectly normal. The default implementation of -description (the method that returns this output) is the name of the class of the object followed by the object's address. In other words, -[NSObject description] is likely to be implemented something like the following:
- (NSString *)description {
return [NSString stringWithFormat:#"<%#: %p>",
NSStringFromClass([self class]),
self];
}
This means that instance variables of your object are not going to be printed. A number of built-in classes do print their instance variables when logged, but this was implemented specifically for that class and is not a generic mechanism. If you want to verify that your Rectangle object is correct, you could implement -description like so:
- (NSString *)description {
return [NSString stringWithFormat:#"<%#: %p width=%d, height=%d>",
NSStringFromClass([self class]),
self,
width,
height];
}
No error! Since your Rectangle class has no description method, calling NSLog(#"%#", rect); will return the class of the object, followed by its address in memory.
If you want to print width and height of the rectangle you may use something like:
in Rectangle.h
#interface Rectangle : NSObject
{
int width;
int height;
}
-(id)initObject;
#property int width, height;
#end
in Rectangle.m
#implementation Rectangle
#synthesize width, height;
-(id)initObject{
if (self = [super init]) {
height = 5;
width = 7;
}
return self;
}
#end
and then call
NSLog(#"width=%d, height=%d", [rect width], [rect height]);
I need to develop a strategy pattern where i have a main class with other three classes where i need to refer to the objects of the other three classes using the main class object.To solve this is the strategy pattern will help me? If so please do give me the syntax in Objective-C?
You'll want to look at Objective-C's protocol mechanism. Here's a simple protocol with a single required method:
#protocol Strategy <NSObject>
#required
- (void) execute;
#end
Then you declare a class that fulfills that protocol:
#interface ConcreteStrategyA : NSObject <Strategy>
{
// ivars for A
}
#end
The implementation must provide the -execute method (since it was declared as #required):
#implementation ConcreteStrategyA
- (void) execute
{
NSLog(#"Called ConcreteStrategyA execute method");
}
#end
You can make a similar ConcreteStrategyB class, but I'm not going to show it here.
Finally, make a context class with a property maintaining the current strategy.
#interface Context : NSObject
{
id<Strategy> strategy;
}
#property (assign) id<Strategy> strategy;
- (void) execute;
#end
Here is the implementation. The method that delegates to the strategy's -execute method just happens to be called -execute as well, but it doesn't have to be.
#implementation Context
#synthesize strategy;
- (void) execute
{
[strategy execute];
}
#end
Now I'll make a few instances and put them to use:
ConcreteStrategyA * concreteStrategyA = [[[ConcreteStrategyA alloc] init] autorelease];
ConcreteStrategyB * concreteStrategyB = [[[ConcreteStrategyB alloc] init] autorelease];
Context * context = [[[Context alloc] init] autorelease];
[context setStrategy:concreteStrategyA];
[context execute];
[context setStrategy:concreteStrategyB];
[context execute];
The console output shows that the strategy was successfully changed:
2010-02-09 19:32:56.582 Strategy[375:a0f] Called ConcreteStrategyA execute method
2010-02-09 19:32:56.584 Strategy[375:a0f] Called ConcreteStrategyB execute method
Note that if the protocol does not specify #required, the method is optional. In this case, the context needs to check whether the strategy implements the method:
- (void) execute
{
if ([strategy respondsToSelector:#selector(execute)])
[strategy execute];
}
This is a common Cocoa pattern called delegation. For more information on delegation and other design patterns in Cocoa, see this.
Here's a bit more of a concrete example. You can put each item in a separate file. I've put it all in one file for ease of understanding.
// main.m
// StrategyWikipediaExample
//
// Created by steve on 2014-07-08.
// Copyright (c) 2014 steve. All rights reserved.
//
#import <Foundation/Foundation.h>
/**
Equivalent to Java Interface
All concrete Strategies conform to this protocol
*/
#protocol MathOperationsStrategy<NSObject>
- (void)performAlgorithmWithFirstNumber:(NSInteger)first secondNumber:(NSInteger)second;
#end
/**
Concrete Strategies.
Java would say they "Extend" the interface.
*/
#interface AddStrategy : NSObject<MathOperationsStrategy>
#end
#implementation AddStrategy
- (void)performAlgorithmWithFirstNumber:(NSInteger)first secondNumber:(NSInteger)second
{
NSInteger result = first + second;
NSLog(#"Adding firstNumber: %ld with secondNumber: %ld yields : %ld", first, second, result);
}
#end
#interface SubtractStrategy : NSObject<MathOperationsStrategy>
#end
#implementation SubtractStrategy
- (void)performAlgorithmWithFirstNumber:(NSInteger)first secondNumber:(NSInteger)second
{
NSInteger result = first - second;
NSLog(#"Subtracting firstNumer: %ld with secondNumber: %ld yields: %ld", first, second, result);
}
#end
#interface MultiplyStrategy : NSObject<MathOperationsStrategy>
#end
#implementation MultiplyStrategy
- (void)performAlgorithmWithFirstNumber:(NSInteger)first secondNumber:(NSInteger)second
{
NSInteger result = first * second;
NSLog(#"Multiplying firstNumber: %ld with secondNumber: %ld yields: %ld", first, second, result);
}
#end
#interface Context : NSObject
#property (weak, nonatomic)id<MathOperationsStrategy>strategy; // reference to concrete strategy via protocol
- (id)initWithMathOperationStrategy:(id<MathOperationsStrategy>)strategy; // setter
- (void)executeWithFirstNumber:(NSInteger)first secondNumber:(NSInteger)second;
#end
#implementation Context
- (id)initWithMathOperationStrategy:(id<MathOperationsStrategy>)strategy
{
if (self = [super init]) {
_strategy = strategy;
}
return self;
}
- (void)executeWithFirstNumber:(NSInteger)first secondNumber:(NSInteger)second
{
[self.strategy performAlgorithmWithFirstNumber:first secondNumber:second];
}
#end
int main(int argc, const char * argv[])
{
#autoreleasepool {
id<MathOperationsStrategy>addStrategy = [AddStrategy new];
Context *contextWithAdd = [[Context alloc] initWithMathOperationStrategy:addStrategy];
[contextWithAdd executeWithFirstNumber:10 secondNumber:10];
}
return 0;
}