method caller mixup

  • I have a couple of node-based classes, one to build a Lempel-Ziv tree (Incremental Parsing) and one to build a Trie. Both of these classes have an -initWithParent: method. Should be fine, I would think, but I'm getting a compiler error that a Trie node's initWithParent is expecting the Lempel-Ziv node as input. I can't see any reason why this would happen. Is there any tricky cause for a matching method name, in a totally different class, to get called? I tried cleaning the project, to no avail.
    It would be too complicated to post the code, but the context of the error is something like this:

    HSMM_TrieNode* newNode = [[HSMM_TrieNode alloc] initWithParent:aNode];

    And yes, "aNode" is very definitely an HSMM_TrieNode, not a Lempel-Ziv node. The HSMM_TrieNode class has no idea that the Lempel-Ziv node class even exists...

    Has anyone seen this kind of mixup?

    thanks,

    J.

    James B Maxwell
    Composer/Doctoral Student
    School for the Contemporary Arts (SCA)
    School for Interactive Arts + Technology (SIAT)
    Simon Fraser University
    <jbmaxwell...>
    <jbmaxwel...>
  • On 17 Apr 2010, at 1:02 PM, James Maxwell wrote:

    > I have a couple of node-based classes, one to build a Lempel-Ziv tree (Incremental Parsing) and one to build a Trie. Both of these classes have an -initWithParent: method. Should be fine, I would think, but I'm getting a compiler error that a Trie node's initWithParent is expecting the Lempel-Ziv node as input. I can't see any reason why this would happen. Is there any tricky cause for a matching method name, in a totally different class, to get called? I tried cleaning the project, to no avail.
    > It would be too complicated to post the code, but the context of the error is something like this:
    >
    > HSMM_TrieNode* newNode = [[HSMM_TrieNode alloc] initWithParent:aNode];
    >
    > And yes, "aNode" is very definitely an HSMM_TrieNode, not a Lempel-Ziv node. The HSMM_TrieNode class has no idea that the Lempel-Ziv node class even exists...
    >
    > Has anyone seen this kind of mixup?

    It's not particularly tricky. +alloc returns an id, and Objective-C doesn't have operand-overloaded methods. There is nothing in your alloc/init expression that tells the _compiler_ which of the differently-defined initWithParent: methods you intend to use, so it picks one in some undefined way. In this case, it picked the one you didn't intend.

    You can force the choice by casting the result of +alloc to the intended type:

    [ (HSMM_TrieNode *)[HSMM_TrieNode alloc] initWithParent: aNode ]

    — F
  • > It's not particularly tricky. +alloc returns an id, and Objective-C doesn't have operand-overloaded methods.
    > There is nothing in your alloc/init expression that tells the _compiler_ which of the differently-defined initWithParent:
    > methods you intend to use, so it picks one in some undefined way. In this case, it picked the one you didn't intend.
    >
    > You can force the choice by casting the result of +alloc to the intended type:
    >
    > [ (HSMM_TrieNode *)[HSMM_TrieNode alloc] initWithParent: aNode ]

    -Wstrict-selector-match would have reported the ambiguity.  Otherwise, the following code compiles without complaint (this is on gcc 4.0; on gcc 4.2 the warning flag might be on by default):

        @interface Class1 : NSObject
        - (id) initWithScalar: (int) i;
        @end

        @interface Class2 : NSObject
        - (id) initWithScalar: (float) f;
        @end

        void test (void)
        {
            Class1 *o1 = [[Class1 alloc] initWithScalar: 1];
            Class1 *o2 = [[Class1 alloc] initWithScalar: 1.0f];
            Class2 *o3 = [[Class2 alloc] initWithScalar: 1];
            Class2 *o4 = [[Class2 alloc] initWithScalar: 1.0f];
        }

    However, two of these four init method invocations will get a parameter in a form (int vs float) they don't expect since the compiler doesn't have enough information to perform the expected implicit type conversion across the call, and that is not good.

    As for the scope and interpretation of method names, this might be worth a look if you haven't already:

    http://developer.apple.com/Mac/library/documentation/Cocoa/Conceptual/Objec
    tiveC/Articles/ocSelectors.html#//apple_ref/doc/uid/TP30001163-CH23-SW1


    Paul Sanders.
  • Thanks folks,

    I actually did wind up type casting the alloc, as recommended. Sorry I didn't post when I found the solution.
    I guess I've just never come across this before, which seems kind of strange... but true.

    cheers,

    J.

    On 2010-04-17, at 12:42 PM, Paul Sanders wrote:

    >> It's not particularly tricky. +alloc returns an id, and Objective-C doesn't have operand-overloaded methods.
    >> There is nothing in your alloc/init expression that tells the _compiler_ which of the differently-defined initWithParent:
    >> methods you intend to use, so it picks one in some undefined way. In this case, it picked the one you didn't intend.
    >>
    >> You can force the choice by casting the result of +alloc to the intended type:
    >>
    >> [ (HSMM_TrieNode *)[HSMM_TrieNode alloc] initWithParent: aNode ]
    >
    > -Wstrict-selector-match would have reported the ambiguity.  Otherwise, the following code compiles without complaint (this is on gcc 4.0; on gcc 4.2 the warning flag might be on by default):
    >
    > @interface Class1 : NSObject
    > - (id) initWithScalar: (int) i;
    > @end
    >
    > @interface Class2 : NSObject
    > - (id) initWithScalar: (float) f;
    > @end
    >
    > void test (void)
    > {
    > Class1 *o1 = [[Class1 alloc] initWithScalar: 1];
    > Class1 *o2 = [[Class1 alloc] initWithScalar: 1.0f];
    > Class2 *o3 = [[Class2 alloc] initWithScalar: 1];
    > Class2 *o4 = [[Class2 alloc] initWithScalar: 1.0f];
    > }
    >
    > However, two of these four init method invocations will get a parameter in a form (int vs float) they don't expect since the compiler doesn't have enough information to perform the expected implicit type conversion across the call, and that is not good.
    > As for the scope and interpretation of method names, this might be worth a look if you haven't already:
    >
    > http://developer.apple.com/Mac/library/documentation/Cocoa/Conceptual/Objec
    tiveC/Articles/ocSelectors.html#//apple_ref/doc/uid/TP30001163-CH23-SW1

    >
    > Paul Sanders.
    >

    James B Maxwell
    Composer/Doctoral Student
    School for the Contemporary Arts (SCA)
    School for Interactive Arts + Technology (SIAT)
    Simon Fraser University
    <jbmaxwell...>
    <jbmaxwel...>
  • On 17.04.10 22:24, James Maxwell wrote:
    > I actually did wind up type casting the alloc, as recommended. Sorry I didn't post when I found the solution.
    > I guess I've just never come across this before, which seems kind of strange... but true.

    By the way: An even better idea is to just change the name, i.e. instead
    of -initWithParent: call it -initWithParentTrieNode:.

    --
    Cheers,
    -- Uli Kusterer
    "The Witnesses of TeachText are everywhere..."
    http://www.zathras.de
  • yes, good point. That would certainly make things simpler.

    J.

    On 2010-04-17, at 1:31 PM, Uli Kusterer wrote:

    > On 17.04.10 22:24, James Maxwell wrote:
    >> I actually did wind up type casting the alloc, as recommended. Sorry I didn't post when I found the solution.
    >> I guess I've just never come across this before, which seems kind of strange... but true.
    >
    > By the way: An even better idea is to just change the name, i.e. instead of -initWithParent: call it -initWithParentTrieNode:.
    >
    > --
    > Cheers,
    > -- Uli Kusterer
    > "The Witnesses of TeachText are everywhere..."
    > http://www.zathras.de

    James B Maxwell
    Composer/Doctoral Student
    School for the Contemporary Arts (SCA)
    School for Interactive Arts + Technology (SIAT)
    Simon Fraser University
    <jbmaxwell...>
    <jbmaxwel...>
previous month april 2010 next month
MTWTFSS
      1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30    
Go to today