I’m trying to learn how to use protocols and extensions to factor out redundant 
function bodies.

Supposedly in a protocol, “Self” is the class implementing the protocol. So it 
seems to me that extension methods should be able to have a return type of Self 
so they can return self, and thus have the extension method behave the same as 
it would as if it were defined in the class adopting the protocol.

But it seems as if that’s not the case, because in the code below, when I 
return “self” from the extension’s function bodies in order to enable method 
chaining, I get a compiler error. I’m told the class is immutable. If I move 
those bodies into the separate classes adopting the protocol and change Self to 
the name of the class, then everything works as expected.

Is it possible to get the code working, or am I tilting at a windmill? I can 
imagine there’s just some minor syntax gotcha of which I’m unaware; but then 
again maybe there’s just no way to return a mutable self from a 
protocol-extension function body.

BTW, I wondered if it was a reference type vs value type thing, so I tested: it 
doesn’t matter whether I define these classes as classes or structs; the error 
message is the same.

import SpriteKit

// Create a protocol specifying the items an action collection
// must have in order for us to do fluent configuration using
// chained method calls

protocol SKActionCollection {
  var list: [SKAction] { get set } // Should be mutable!
  var action: SKAction { get }
}

// Use an extension to define methods common to both types
// of action collection

extension SKActionCollection {

  mutating func withAction( target: SKAction )
    -> Self
  {
    list.append( target )
    return self
  }

  mutating func withBlock( block: ()->() )
    -> Self
  {
    return withAction( SKAction.runBlock( block ))
  }

  mutating func withDelay( duration: NSTimeInterval )
    -> Self
  {
    return withAction( SKAction.waitForDuration( duration ))
  }

  // ... Many other useful mutating functions omitted

  func performOnceOn( node: SKNode )
  {
    node.runAction( action )
  }

}

extension SKAction {
  struct Fluent {

    // Fluent configuration for an action collection which
    // runs the actions sequentially

    class Sequence : SKActionCollection {
      var list = [SKAction]()
      var action: SKAction {
        return SKAction.sequence( list )
      }
    }

    // Fluent configuration for an action collection which
    // runs the actions concurrently

    class Group : SKActionCollection {
      var list = [SKAction]()
      var action: SKAction {
        return SKAction.group( list )
      }
    }

  }
}

// Try to use fluent configuration to define action collections

// I get the same error, saying my function call (to the constructor?)
// returns an immutable value, regardless of whether I use var or let

var sequence = SKAction.Fluent.Sequence()
  .withDelay( 0.5 )
  .withBlock( { print( "I did something in sequence!" ) } )
  .action

let group = SKAction.Fluent.Group()
  .withBlock( { print( "A group of one action is really pitiful" ) } )
  .action


-- 

Charles
_______________________________________________

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Reply via email to