Is there a way to have "private" methods in a superclass (which are not in its header file) and still be able to access these from subclasses?
You could use a custom category, for example:
Stuffy.h
// The "official" header file to be used by almost anyone
#interface Stuffy {
int myMember;
}
- (void) somePublicMethod;
#end
Stuffy+Secret.h
// The magic header file, which should only be used by knowledgable people
#import "Stuffy.h"
#interface Stuffy (Secret)
- (void) _pseudoProtectedMethod;
#end
Stuffy.m
#import "Stuffy+Secret.h"
#implementation Stuffy
- (void) somePublicMethod {
// ...
}
#end
#implementation Stuffy (Secret)
- (void) _pseudoProtectedMethod {
// ...
}
#end
Subclasses of Stuffy can now either import Stuffy.h in their .m files and stick to the public API, or import Stuffy+Secret.h and use the semi-protected stuff.
Note, that Objective-C has no true notion of protected or private methods. Basically, anyone can include Stuffy+Secret.h and use the stuff declared there.
You can "cheat" several ways. In addition to categories, you can simply cast your Stuffy pointer to FunnyStuff, and have a whole 'nother #interface for it. (Just don't declare any statics and don't do an #implementation.) Or, a little cleaner, cast to an #protocol that defines your added methods. (And, since you're doing a subclass, you can simply add the protocol to your subclass definition, and avoid any casting.)
Keep in mind that Objective-C doesn't require that every method in an #implementation have a corresponding declaration in #interface, and method calls are entirely dynamic, effectively including name look-up. The only thing you have to do is to trick the compiler into allowing the call. (In fact, you can make the call with no declaration at all if you don't mind the compiler warning.)
Related
This question already has answers here:
Best way to define private methods for a class in Objective-C
(12 answers)
Closed 9 years ago.
I have a class which has some methods that are only to be used within the class itself. These methods exist because I have a three-step process for the graphics work I'm doing, but I only want instances of the class to access the final result of those calculations, in a simplified example:
#import <Foundation/Foundation.h>
#interface GraphicsWorld : NSObject
#property(nonatomic, strong) NSMutableArray *objects;
#property(nonatomic, strong) NSMutableArray *adjustedObjects
/* three methods I'll never use outside of this class
I want to find a way to get replace these methods.
*/
-(void) calcTranslation;
-(void) calcRotation;
-(void) calcPerspective;
/* the one method I'll use outside of this class */
-(NSMutableArray *) getAdjustedObjects;
#end
I could define c-functions just outside of my implementation for this, but then they wouldn't have access to the properties:
#import <Foundation/Foundation.h>
#import "GraphicsWorld.h"
void calcTranslation()
{
// I'm useless because I can't access _objects.
}
void calcRotation()
{
// Hey, me too.
}
void calcPerspective()
{
// Wow, we have a lot in common.
}
#implementation GraphicsWorld
-(NSMutableArray *) getAdjustedObjects
{
calcTranslation();
calcRotation();
calcPerspective();
return adjustedObjects;
}
#end
Unless I'm misunderstanding your question, it sounds like you just want to hide your methods from being public? If so, just delete them from the header. You no longer need to declare methods in advance in objc (Xcode). The compiler will just find them internally now.
Make C-style functions (as you've shown) that take arguments and return values.
Make private Objective-C-style methods.
In addition to your #implementation section in the .h file, you can also have one in your .m file, which is private. Just as you declare methods and properties in the .h file's #implementation, you can do the same in the .m.
A method can be called whether it is declared private, or not put in the header file; due to the nature of Objective-C hiding methods is hard.
Hiding functions is a lot easier, just declare them static. To access the current instance you just pass in a reference to it - i.e. exactly what Objective-C does behind the scenes.
So for example:
void calcTranslation(GraphicsWorld *self)
{
// Access properties, instance variables, call instance methods etc.
// by referencing self. You *must* include self to reference an
// instance variable, e.g. self->ivar, as this is not a method the
// self-> part is not inferred.
}
and to call it:
-(NSMutableArray *) getAdjustedObjects
{
calcTranslation(self);
...
I am learning object orientated programming from the online Stanford courses there is a part I am unsure of regarding declarations. I thought that you must always declare the prototype in the header and then write the code in the implementation file, but the professor wrote a method in the implementation without a declaration prototype in the header file, how come?
Also, may someone please clear the difference between private and public and if the method without a prototype is public or private? The method without a prototype is not from a super class.
That is a perfectly legal way to declare methods that are not to be used outside the class implementation itself.
The compiler will find methods in the implementation file as long as they precede the method in which they are used. However that will not always be the case, as the new LLVM compiler allows methods to be declared in any order and referenced from a given file.
There are a couple of different styles for declaring methods inside an implementation file:
//In the Header File, MyClass.h
#interface MyClass : NSObject
#end
//in the implementation file, MyClass.m
//Method Decls inside a Private Category
#interface MyClass (_Private)
- (void)doSomething;
#end
//As a class extension (new to LLVM compiler)
#interface MyClass ()
- (void)doSomething;
#end
#implementation MyClass
//You can also simply implement a method with no formal "forward" declaration
//in this case you must declare the method before you use it, unless you're using the
//latest LLVM Compiler (See the WWDC Session on Modern Objective C)
- (void)doSomething {
}
- (void)foo {
[self doSomething];
}
#end
If you write the method in you header file it is public and accessible for other classes / objects. If you do not declare it in the header file the method is a private method meaning that you can access it internally in you class but no other class can use this method.
I'm writing a media player framework for a project I'm working on. This depends on VLC. One of my classes' header file looks like this
#import <vlc/vlc.h>
#interface MediaPlayerVLC : MediaPlayer
{
libvlc_media_player_t *player;
libvlc_media_t *media;
}
#end
I need the instance variables in the class, and I need the #import <vlc/vlc.h>, because they're defined in there. But I don't want users of this framework to have to import all of VLC's headers just for these two types. I've seen a few solutions to this problem around...
Forward declaration, such as #class. Unfortunately, these types are typedef struct types, I can't seem to find any way to forward declare them
declare the ivars as void *, then cast them whenever I want to use them. I'd like to avoid this if possible, as we lose type-safety and implementation files become full of ugly casts.
I've seen this in Apple's frameworks...
#interface CAAnimation : NSObject <NSCoding, NSCopying, CAMediaTiming, CAAction>
{
#private
void *_attr;
uint32_t _flags;
}
What does _attr point to? I guess it would be a struct of ivars, I'm curious what advantages this has...
Two header files for the class, one public and one private. The private one would look like the above, and the public would just have void * pointers. This is pretty ugly, as I'd have to be very careful to keep them both in sync.
What's considered best practise? Is there an approach I've missed?
You can use class extensions. You should try doing this:
MediaPlayerVLC.h:
#interface MediaPlayerVLC : MediaPlayer
{
}
#end
MediaPlayerVLC.m:
#import "MediaPlayerVLC.h"
#import <vlc/vlc.h>
#interface MediaPlayerVLC ()
{
libvlc_media_player_t *player;
libvlc_media_t *media;
}
#end
#implementation MediaPlayerVLC
// The implementation
#end
From Apple's docs:
Class extensions are like anonymous categories, except that the
methods they declare must be implemented in the main #implementation
block for the corresponding class.
Using the Clang/LLVM 2.0 compiler,
you can also declare properties and instance variables in a class
extension.
That's using a class extension category to declare extra ivars in the implementation file.
With the newest compiler you can also declare ivars in your class's #implementation section:
// MediaPlayerVLC.m
#import "MediaPlayerVLC.h"
#import <vlc/vlc.h>
#implementation MediaPlayerVLC
{
libvlc_media_player_t *player;
libvlc_media_t *media;
}
...
#end
You can put ivars in implementation like
#implementation Something
{
int a;
}
In objective-c it is possible to add a #dynamic to a property.
Is this also possible for normal instance methods?
EDIT
I think i wasn't clear enough.
I want to do the following:
#interface MyClass
#property (retain) NSObject *somePropertyObject;
- (void) myMethod;
#end
#implementation MyClass
#dynamic somePropertyObject;
//Make myMethod dynamic. I do not want to implement it. Like C++ Virtual
#end
If you mean "How can I declare a method, but not provide a definition which I will subsequently provide at runtime?" Then it's easy, just use a category. Like this:
#interface MyObject : NSObject
// Methods I'll define
- (void)doFoo;
#end
#interface MyObject (DynamicallyProvidedMethods)
// Methods I won't
- (void)myDynamicMethod;
#end
#implementation MyObject
// Methods I'll define
- (void)doFoo
{
}
#end
The compiler will not complain, however if you call -myDynamicMethod at runtime, unless you have provided an implementation for it somehow, it will crash with "unrecognized selector." You can, of course, test for that at runtime by calling respondsToSelector:.
Relatedly, if you're looking to do a near-equivalent of a base class pure virtual method, I would recommend providing an empty implementation that asserts when called if it has not been overridden by a subclass. You can do that like so:
NSAssert((class_getInstanceMethod([self class], _cmd) == class_getInstanceMethod([MyObject class], _cmd)),
#"Subclass of %# must override -%#",
NSStringFromClass([MyObject class]),
NSStringFromSelector(_cmd));
// ...where overridesSelector:ofBaseClass: looks like:
//
// return ;
Of course, that won't alert you to problems at compile time, but it's better than nothing.
HTH
I think you might be asking how to declare a method that will be implemented some time later somewhere else.
The Objective-C way to do that is to use Protocols.
You declare a protocol like this, usually in a header file
#protocol MyProtocol <NSObject> {
#optional
- (void)optionalMethod;
#required
- (void)requiredMethod;
}
#end
This declares two methods, one which is optional and one is required. To use this protocol you declare the conformance when declaring the class that will implement the protocol
#interface MyConformingClass : NSObject <MyProtocol> {
}
// you don't have to redeclare methods that are declared in the protocol
#end
This new class is checked at compile time for the implementation of requiredMethod so it has to implement it, but it can choose whether or not to implement the optionalMethod
Now, any class that requires instances of objects to conform to the protocol can declare this, for example, in the interface
#interface RequiringClass : NSObject {
MyConformingClass <MyProtocol> *conformingClassObject;
}
…
#end
Again, this is checked at compile time
To make sure that the conforming class implement the #optional methods, we can use this handy structure
if [conformingClassObject respondsToSelector:#selector(optionalMethod)] {
[conformingClassObject optionalMethod];
} else {
// Do something here because the optional method isn't provided
}
Examples of this are all over Cocoa - it's a class can provide a list of actions that it would like to farm out to it's delegate, the delegate adopts the protocol and provides the implementations of those delegate methods. The calling object can then check if this delegate responds to those methods at runtime as I've described above, and call those methods to perform actions, or provide information where ever it needs to.
This is used quite a lot in Objective-C, where classes provide a list of methods that they would like some other class to perform, unlike virtual functions, where a class declares functions it wants subclasses to provide implementations for. Particularly as Composition is favoured over inheritance in the language. Rather than create a subclass to provide an implementation, you just create another class that can do the same thing, and add a reference to that in the class instead.
No.
#dynamic is just an instruction to the compiler that says: "Don't bother generating accessors for this property, I'm going to provide my own."
Using #dynamic with other methods wouldn't be helpful because the compiler doesn't generate any methods other than accessors for you, and of course you're supplying the other methods anyway.
What are you trying to accomplish?
I have a class (MyClass) with a lot of methods. Consequently, the .m file has become quite difficult to read. I'm relatively new to Objective-C (having come from REALbasic) and I was wondering if it's possible to put some of the methods in MyClass into different files and then include them in the class. How would I go about this in Xcode?
Yes it is possible and fortunately this can be done easily in Objective-C with Categories.
Say you have your base class MyClass.
#interface MyClass : NSObject
-(void) methodA;
#end
And the according implementation file (not relevant here).
Then you can create a category by defining a new interface in a new header file:
// the category name is in parenthesis, can be anything but must be unique
#interface MyClass (extended)
-(void) methodB;
#end
and the implementation file:
#implementation MyClass (extended)
-(void) methodB {
}
#end
Common convention to name these files is ClassToAddMethodsTo+CatgoryName, i.e.:
MyClass+extended.h
MyClass+extended.m
Group related functionality into categories and give it a meaningful name.
In Objective-c you can break a class into 'categories' - a class spread across many files. The normal Object-Oriented way is to use SuperClasses and SubClasses.
This is almost certainly a code smell telling you that you have a design problem. See this antipattern
There is one thing you could do..........
But be warned, some might consider this pure blasphemy. :)
Say you have a class with two methods you want to have in separate files.
You'll have three files:
• Class.h
• Class.m
• Class_otherMethod.m
Your Class.h should look just like any other. I think it's better to keep the header file complete, but this 'trick' can work on separating .h files just as well.
#interface Class : NSObject
- (void) method;
- (void) otherMethod;
#end
In your Class.m file you will #include the Class_otherMethod.m inside the Class #implementation like this:
#import "Class.h"
#implementation Class
- (void) method {
// do something.
}
#include "Class_otherMethod.m"
#end
And your Class_otherMethod.m file will have only the bare otherMethod implementation:
- (void) otherMethod {
// do something different.
}
Why this works
It's quite simple actually. The preprocessor simply "pastes" the content of Class_otherMethod.m inside the Class.m file and the compiler treats it as one big long file. :P