[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: Need help understanding subclassing issue
From: |
hns |
Subject: |
Re: Need help understanding subclassing issue |
Date: |
Thu, 19 Feb 2009 23:23:49 -0800 (PST) |
User-agent: |
G2/1.0 |
On 19 Feb., 22:35, Pierre Bz <p...@ogopogo.biz> wrote:
> I am having problems with writing a subclass.
> I wrote a simplified (trivial) subclass of NSDictionary
> and it fails. I need help understanding why.
> I've attempted include all necessary information in this post
> so someone knowledgeable has the information he needs to
> offer a suggestion.
>
> TIA
>
> test result:
> vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
>
> 2009-02-19 16:17:21.760 testcase[12478] testDictionary {Key = Val; }
> 2009-02-19 16:17:21.766 testcase[12478] This exception was raised:
> <NSException: 0x811dd70> NAME:NSGenericException
> REASON:subclass OGBanner(instance) should override count
>
> ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>
> testcase.m:
> vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
> #import <Foundation/Foundation.h>
> #import "banner.h"
> int main( void )
> {
> /*
> * This is a reduced test to illustrate my problem.
> * OGBanner is a subclass of NSDictionary.
> * It does nothing except for being a new name for NSDictionary.
> * Yet it fails to work.
> *
> * When I got the exception message, I added the implementation
> * of count in banner.m and banner.h, but to no avail.
> */
> NSAutoreleasePool * pool;
> NSDictionary * testDictionary;
> OGBanner * testBanner;
> NSString * key = @"Key";
> NSString * val = @"Val";
> pool = [NSAutoreleasePool new];
>
> testBanner = [[OGBanner alloc] initWithObjects: &val forKeys: &key count:
> 1];
> testDictionary = [[NSDictionary alloc] initWithObjects: & val
> forKeys: & key count: 1];
> NSLog( @"testDictionary %@", testDictionary ); /* This works */
> NS_DURING
> {
> NSLog( @"testBanner %@", testBanner ); /* This does not work */
> }
> NS_HANDLER
> {
> NSLog( @"This exception was raised: %@", localException );
> }
> NS_ENDHANDLER;
> return EXIT_SUCCESS ;}
>
> ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>
> banner.h:
> vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
> #import <Foundation/Foundation.h>
>
> @interface OGBanner : NSDictionary
> {
>
> }
>
> - (id) initWithObjects: (id *) objects
> forKeys: (id *) keys count: (unsigned ) count;
> - (unsigned) count;
> @end
>
> ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> banner.m:
> vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
> #import <Foundation/Foundation.h>
> #import "banner.h"
>
> @implementation OGBanner : NSDictionary
>
> - (id) initWithObjects: (id *) objects
> forKeys: (id *) keys
> count: (unsigned) count
> {
> return [super initWithObjects: objects forKeys: keys count: count];
>
> }
>
> - (unsigned) count
> {
> return [super count];
>
> }
>
> @end;
>
> ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>
> GNUmakefile
> vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
>
> include $(GNUSTEP_MAKEFILES)/common.make
>
> TOOL_NAME = testcase
>
> testcase_HEADERS = banner.h
> testcase_OBJC_FILES = testcase.m banner.m
> testcase_RESOURCE_FILES =
>
> include $(GNUSTEP_MAKEFILES)/tool.make
>
> ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>
> Details of the development environment
> vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
> Work bench information
> GNUSTEP_HOST_CPU = ix86
> GNUSTEP_HOST_OS = linux-gnu
> MAKE_VERSION = GNU Make 3.81
> GCC_VERSION = gcc (GCC) 4.2.4 (Ubuntu 4.2.4-1ubuntu3)
> LIBRARY_COMBO = gnu-gnu-gnu
> KERNEL_NAME = Linux
> KERNEL_RELEASE = 2.6.24-23-generic
> KERNEL_VERSION = #1 SMP Mon Jan 26 00:13:11 UTC 2009
> MACHINE = i686
> arguments = (obj/benchinfo)
> globallyUniqueString = homard_2d8f_f4dfe20_0
> processName = benchinfo
> hostName = homard
> operatingSystemName = GSGNULinuxOperatingSystem
> operatingSystemVersionString = 2.6.24-23-generic
> ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
To give a short answer: you can't easily subclass NSDictionary.
It is a so called "Class Cluster", i.e. NSDictionary is an abstract
class whose alloc and init methods may return a (private) subclass
object which does not know about your subclass.
The error message "NSGenericException REASON:subclass OGBanner
(instance) should override count" gives a hint: NSDictionary expects
that all subclasses implement a -count method. This is provided by the
private subclasses of NSDictionary but missing in your OGBanner.
How to solve it:
* either reduce your model to use only a category of NSDictionary
* redesign your "is a dictionary" class relation to a "has a
dictionary". i.e. subclass OGBanner from NSObject and provide an
NSDictionary instance variable
-- hns
- Re: Need help understanding subclassing issue,
hns <=