1

Update: The question voted to close this as duplicate deals with self.init() which can be solved by marking class final or requiring init. But How does that work on Repositories or return from any other method other than init (My Implementation is @NSManaged Object)

Here is what I want to do. Get a JSON Via Request, then parse it into an object.

var req = Request("http://somewhere/story/get/1")
var story = req.parseJsonResponse() as Story

The Request class somehow looks like this:

class Request {

    public var httpJsonResponse : String

    init(_ url : String) {
        //This comes from HTTP
        httpJsonResponse = "{}"
    }

    public func parseJsonResponse<T : IParse>() -> T {

        return T.parse(json: httpJsonResponse)

    }

}

Now, I want to make sure that IParse implementation has parse method:

protocol IParse {
    static func parse(json : String) -> Self
}

So far so good, here's the problem with implementation:

class Story : IParse {
    required init() 
    {
    }
    public static func parse(json: String) -> Self
    {
        //return self.init() works thanks to @tomahh
        return StoryRepo.ById(1)
    }

}

class StoryRepo {
    public static func ById(_ id : Int) -> Story {
        return Story()
    }
}

This does not work. Neither of these work:

  1. Returning Story
  2. Casting Story() as! Self

See updated playground gist.

tika
  • 7,135
  • 3
  • 51
  • 82
  • Does not work on my playground too.Whether I don't understand it or it's a bug. `cannot convert return expression of type 'Story' to return type 'Self'` – user3581203 Feb 28 '17 at 01:43
  • Possible duplicate of [Protocol func returning Self](http://stackoverflow.com/questions/25645090/protocol-func-returning-self) – Hamish Feb 28 '17 at 01:49
  • 1
    Either make `Story` `final`, or implement a `required` initialiser, and call that on `self` in the static method. – Hamish Feb 28 '17 at 01:51
  • @Hamish In case we are returning the value? – tika Feb 28 '17 at 02:13
  • @tika I'm not sure I understand you. Marking the class as `final` allows you to achieve this without adding a `required` initialiser. – Hamish Feb 28 '17 at 11:08
  • @Hamish it does not build for `return StoryRepo.ById(1)` but builds for `return self.init()` in the `parse` method – tika Feb 28 '17 at 20:41
  • @tika Replace `-> Self` with `-> Story`. – Hamish Feb 28 '17 at 20:43

1 Answers1

1
class Story : IParse {
    required init() 
    {
    }

    public static func parse(json: String) -> Self
    {
        return self.init()
    }
}

This will work. This makes sure that you actually build an instance of Self, so that a Tale subclass of Story would not create a boring Story, but a wonderful tale indeed.

The required keyword forces subclasses to override this init, so that we are sure it is valid to actually call self.init() within parse.


Another solution, if you don't want to struggle with inheritance, would have been to make the Story class final

final Story: IParse {
  public static func parse(json: String) -> Story {
    return Story()
  }
}

In this example, because Story will never be inherited from, it is safe to call Story() and return a Story type from the parse function.

tomahh
  • 13,441
  • 3
  • 49
  • 70
  • Doesn't work. Can you try on your playground. `use of unresolved identifier 'Self' return Self()` – tika Feb 28 '17 at 01:50
  • Oops, I updated my answer with valid code. Sorry for the misleading first contribution. I'm updating again with more explanation right now! – tomahh Feb 28 '17 at 01:53
  • See the updated section. How can it implement with result from other methods? – tika Feb 28 '17 at 02:12