discuss-gnustep
[Top][All Lists]
Advanced

[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


reply via email to

[Prev in Thread] Current Thread [Next in Thread]