Specifying A Dynamic Type In Swift Generics


(Jon Akhtar) #1

I have a generic class that I would like to use. I¹ll include the whole
source.

public final class EventRegistration<E: AppEvent> {
  private(set) var event: E?
  private var token: AnyObject?

  public init() {}

  public init(event: AppEvent, token: AnyObject) {
    self.event = event
    self.token = token
  }

  public func unregister() {
    if let token = self.token,
          let event = self.event {
      event.unregister(token)
    }
    token = nil
    event = nil
  }

  public var isRegistered: Bool {
    return token != nil
  }

  deinit {
    unregister()
  }
}

I would like to use this class in my AppEvent class. Among other things
AppEvent has a method register()

public class AppEvent : CustomStringConvertible {

Š

  public func register(notification: (NSNotification! ->
Void))->EventRegistration<???> {
    let eventName = self.dynamicType.eventName()

    let token =
NSNotificationCenter.defaultCenter().addObserverForName(eventName, object:
nil, queue: self.dynamicType.eventQueue(), usingBlock: notification)

    let registration = EventRegistration(event: self, token: token)

    return registration
}

I have 50-100 subclasses of AppEvent that I use directly.

public class SomeEvent: AppEvent {}
public class SomeOtherEvent: AppEvent {}
public class EvenSomeOtherEvent: AppEvent {}

They all inherit the register() function.

I would like the following.

Let some = SomeEvent().register() { note in }

some.event.self should be ³SomeEvent²

Because SomeEvent.register() returns EventRegistration<SomeEvent>

All the parts are there for this to be statically typed. If I implemented
register in each class I could get the behavior I want. What I am looking
for is a way to say ³the current dynamic type², sort of like ³Self².

Is there a signature for "public func register(notification:
(NSNotification! -> Void))->EventRegistration<???>" that would accomplish
this, or does this break some type rule I am not aware of, or is it just a
missing language feature.

If you want points, see:
http://stackoverflow.com/questions/38193012/specifying-a-dynamic-type-in-sw
ift-generics

Thanks,

Jon


(Kenny Leung) #2

So, restating the question:

You want to have a method on a class such that it will return an object which is genericised with that class. Like:

class A {
    func createB() -> B<Self> {
    }
}

So that if you have C which is a subclass of A, calling createB() would return B<C>, and not B<A>

Is that correct?

-Kenny

···

On Jul 5, 2016, at 8:40 AM, Jon Akhtar via swift-users <swift-users@swift.org> wrote:

I have a generic class that I would like to use. I¹ll include the whole
source.

public final class EventRegistration<E: AppEvent> {
  private(set) var event: E?
  private var token: AnyObject?

  public init() {}

  public init(event: AppEvent, token: AnyObject) {
    self.event = event
    self.token = token
  }

  public func unregister() {
    if let token = self.token,
          let event = self.event {
      event.unregister(token)
    }
    token = nil
    event = nil
  }

  public var isRegistered: Bool {
    return token != nil
  }

  deinit {
    unregister()
  }
}

I would like to use this class in my AppEvent class. Among other things
AppEvent has a method register()

public class AppEvent : CustomStringConvertible {

Š

  public func register(notification: (NSNotification! ->
Void))->EventRegistration<???> {
    let eventName = self.dynamicType.eventName()

    let token =
NSNotificationCenter.defaultCenter().addObserverForName(eventName, object:
nil, queue: self.dynamicType.eventQueue(), usingBlock: notification)

    let registration = EventRegistration(event: self, token: token)

    return registration
}

I have 50-100 subclasses of AppEvent that I use directly.

public class SomeEvent: AppEvent {}
public class SomeOtherEvent: AppEvent {}
public class EvenSomeOtherEvent: AppEvent {}

They all inherit the register() function.

I would like the following.

Let some = SomeEvent().register() { note in }

some.event.self should be ³SomeEvent²

Because SomeEvent.register() returns EventRegistration<SomeEvent>

All the parts are there for this to be statically typed. If I implemented
register in each class I could get the behavior I want. What I am looking
for is a way to say ³the current dynamic type², sort of like ³Self².

Is there a signature for "public func register(notification:
(NSNotification! -> Void))->EventRegistration<???>" that would accomplish
this, or does this break some type rule I am not aware of, or is it just a
missing language feature.

If you want points, see:
http://stackoverflow.com/questions/38193012/specifying-a-dynamic-type-in-sw
ift-generics

Thanks,

Jon

_______________________________________________
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users


(Jon Akhtar) #3

Yes, that is what I thought too. But when I try to do it, I get this error:

Error:(57, 23) 'Self' is only available in a protocol or as the result of
a method in a class; did you mean 'AppEvent’?

Thanks,

Jon

On 7/5/16, 12:15, "swift-users-bounces@swift.org on behalf of Kenny Leung
via swift-users" <swift-users-bounces@swift.org on behalf of

···

swift-users@swift.org> wrote:

So, restating the question:

You want to have a method on a class such that it will return an object
which is genericised with that class. Like:

class A {
   func createB() -> B<Self> {
   }
}

So that if you have C which is a subclass of A, calling createB() would
return B<C>, and not B<A>

Is that correct?

-Kenny

On Jul 5, 2016, at 8:40 AM, Jon Akhtar via swift-users >><swift-users@swift.org> wrote:

I have a generic class that I would like to use. I¹ll include the whole
source.

public final class EventRegistration<E: AppEvent> {
  private(set) var event: E?
  private var token: AnyObject?

  public init() {}

  public init(event: AppEvent, token: AnyObject) {
    self.event = event
    self.token = token
  }

  public func unregister() {
    if let token = self.token,
          let event = self.event {
      event.unregister(token)
    }
    token = nil
    event = nil
  }

  public var isRegistered: Bool {
    return token != nil
  }

  deinit {
    unregister()
  }
}

I would like to use this class in my AppEvent class. Among other things
AppEvent has a method register()

public class AppEvent : CustomStringConvertible {

Š

  public func register(notification: (NSNotification! ->
Void))->EventRegistration<???> {
    let eventName = self.dynamicType.eventName()

    let token =
NSNotificationCenter.defaultCenter().addObserverForName(eventName,
object:
nil, queue: self.dynamicType.eventQueue(), usingBlock: notification)

    let registration = EventRegistration(event: self, token: token)

    return registration
}

I have 50-100 subclasses of AppEvent that I use directly.

public class SomeEvent: AppEvent {}
public class SomeOtherEvent: AppEvent {}
public class EvenSomeOtherEvent: AppEvent {}

They all inherit the register() function.

I would like the following.

Let some = SomeEvent().register() { note in }

some.event.self should be ³SomeEvent²

Because SomeEvent.register() returns EventRegistration<SomeEvent>

All the parts are there for this to be statically typed. If I
implemented
register in each class I could get the behavior I want. What I am
looking
for is a way to say ³the current dynamic type², sort of like ³Self².

Is there a signature for "public func register(notification:
(NSNotification! -> Void))->EventRegistration<???>" that would
accomplish
this, or does this break some type rule I am not aware of, or is it
just a
missing language feature.

If you want points, see:

http://stackoverflow.com/questions/38193012/specifying-a-dynamic-type-in-
sw
ift-generics

Thanks,

Jon

_______________________________________________
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users

_______________________________________________
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users