hfossli
hfossli

Reputation: 22962

Is it possible to hide the inheritance of classes?

From the outside I would like my class to appear like this

@interface MYCardGroupView : UIView
@property (nonatomic, strong) NSArray *cardObjects;
@end

But within the class itself I want it to actually be a UITableView

@interface MYCardGroupView : UITableView <UITableViewDataSource, UITableViewDelegate>
@property (nonatomic, strong) NSArray *cardObjects;
@end

Arguments for:

Upvotes: 3

Views: 565

Answers (5)

hfossli
hfossli

Reputation: 22962

This works from a functional perspective, but has following drawbacks

  • throws error in +[MYCardGroupView alloc]: Incompatible pointer types returning 'MYPrivateCardGroupView *' from a function with result type 'MYCardGroupView *'
  • the extra work of having to declare everything twice

.h-file

@interface MYCardGroupView : UIView
@property (nonatomic, strong) NSArray *cardObjects;
@end

.m-file

#import "MYCardGroupView.h"

@interface MYPrivateCardGroupView : UITableView <UITableViewDataSource, UITableViewDelegate>
@property (nonatomic, strong) NSArray *cardObjects;
@end

@implementation MYCardGroupView

+ (id)alloc
{
    return [MYPrivateCardGroupView alloc];
}

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if(self)
    {
        NSLog(@"My class is %@", [self class]);
    }
    return self;
}

@end

@implementation MYPrivateCardGroupView

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if(self)
    {
        NSLog(@"My class is %@", [self class]);
    }
    return self;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return 10;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell *cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:nil];
    cell.textLabel.text = @"hello";
    return cell;
}

@end

Logs

My class is MYPrivateCardGroupView

Upvotes: 0

CRD
CRD

Reputation: 53000

What you are after is effectively a class cluster, with a cluster size of 1 - unusual maybe but quite legitimate.

A number of classes in the standard frameworks; e.g. NSString; are implemented as clusters where the public class is "abstract" (not in the traditional OO sense) and one or more private classes provide the actual implementation(s). On creating an instance of the public class its init (or alloc) substitutes and instance of one of the private classes.

This is a well defined model in Cocoa, see Apple's Cocoa Core Competencies: Class Cluster

Upvotes: 1

Hot Licks
Hot Licks

Reputation: 47729

One could, in theory, employ two separate .h files, one "real" one, only named "MyClass_real.h" and one fake one, named "MyClass.h". Include the real one in your .m but use the fake one as the advertised interface. The fake one could say your base class is "Potato" and it wouldn't make any difference.

(One would have to be a bit concerned about ARC, I suppose. It might get upset.)

Upvotes: 4

Tommy
Tommy

Reputation: 100622

You can declare the protocols outside of the header (via a class extension — an unnamed category) but not technically the inheritance. That's because usually you want the inheritance to be known.

Immediately obvious workarounds include:

  • declare the public class which is a sub of UIView, have its init or alloc substitute an instance of another class that otherwise follows the same published interface but is a sub of UITableViewController; and
  • use the deprecated class_setSuperclass (deprecated since day one but still available) to change your superclass at init.

Upvotes: 2

Gavin
Gavin

Reputation: 8200

You can hide the protocols it implements (like UITableViewDataSource and UITableViewDelegate) by adding them to a class extension in your .m file. But you can't hide that it's a UITableView subclass.

However, it shouldn't hurt performance to have an extra UIView, at least not in any noticeable way. There are extra views that you don't notice all over the place in the built-in UIKit elements, and the impact is likely very minimal. If you're that worried about performance, leave it as a UITableView subclass. But if you're not so worried and you care more about concealing as much as possible, make it a UIView subclass and have it encapsulate a UITableView instead.

Upvotes: 2

Related Questions