Well, that's not really any different than a switch statement, in that it has to be maintained.
> On Nov 15, 2016, at 01:50 , Jeremy Pereira <jeremy.j.pere...@googlemail.com> > wrote: > > Perhaps I’m missing something here, but why not use a map? > > let factoryMap = [ String : () -> SuperClassOrCommonProtocol ] = [ > “MySubClass" : { return MySubClass() }, … ] > > … > > guard let factoryMethod = factoryMap[theClassName] else { /* error */ } > return factoryMethod() > > This is an approach I always ended up taking in Objective-C anyway, because, > if you don’t know what’s in the string, you need to validate it (imagine if > the user of your app finds out that they can cause you to instantiate any > arbitrary class) and if you do know what’s in the string, why are you not > creating the instance directly? > > >> On 14 Nov 2016, at 23:48, Rick Mann via swift-users <swift-users@swift.org> >> wrote: >> >> Thanks, David. That's interesting as a thought exercise, but doesn't really >> get me away from having switch statements. I'll probably end up just >> "slightly polluting" my classes by adding extension methods to create the >> appropriate auxiliary classes. Sure wish Swift supported optional methods >> without @objc (I guess it's not that big a deal to use @objc). >> >>> On Nov 13, 2016, at 11:19 , David Sweeris <daveswee...@mac.com> wrote: >>> >>> >>>> On Nov 13, 2016, at 1:55 AM, Rick Mann <rm...@latencyzero.com> wrote: >>>> >>>> >>>>> On Nov 12, 2016, at 22:47 , David Sweeris <daveswee...@mac.com> wrote: >>>>> >>>>> >>>>>> On Nov 13, 2016, at 00:38, Rick Mann via swift-users >>>>>> <swift-users@swift.org> wrote: >>>>>> >>>>>> So, it seems there's still no way to do something like instantiate a >>>>>> class given only its name (as a String)? >>>>>> >>>>>> In my situation, I have a number of subclasses (or protocol >>>>>> implementations), which parallel some other class hierarchy. I need to >>>>>> dynamically create one based on the name of another. I don't want the >>>>>> latter classes to "know" anything about the former. >>>>> >>>>> Not that I know of... If this is all your code, can you fake it by >>>>> switching over the type's name? >>>> >>>> Yeah, it just happens in a few places, would be nice to write the code >>>> once and then just ensure classes exist. I know I could do it subclassing >>>> NSObject, but Swift really ought to have proper reflection. >>> >>> Reflection is on the todo list (although I can’t recall if it’s in-scope >>> for Swift 4). >>> >>> There’s also the possibility of putting the names of the classes you want >>> to instantiate into an enum. In fact, if all the classes in question have a >>> common superclass, you could this: >>> class MyAwesomeSuperClass { required init() {} } >>> class MyAwesomeSubClass : MyAwesomeSuperClass {} >>> class Whatever : MyAwesomeSuperClass {} >>> class Etc : Whatever {} >>> enum ClassNames : String { >>> //Unfortunately the value of each case has to be a literal, so >>> //you can’t just say `case etc = "\(Etc.self)"` >>> case myAwesomeSuperClass = "MyAwesomeSuperClass" >>> case myAwesomeSubClass = "MyAwesomeSubClass" >>> case whatever = "Whatever" >>> case etc = "Etc" >>> init(_ instance: MyAwesomeSuperClass) { self = ClassNames.init(rawValue: >>> "\(type(of: instance))")! } >>> init(_ type: MyAwesomeSuperClass.Type) { self = ClassNames.init(rawValue: >>> "\(type)")! } >>> var type: MyAwesomeSuperClass.Type { >>> switch self { >>> case .myAwesomeSuperClass: return MyAwesomeSuperClass.self >>> case .myAwesomeSubClass: return MyAwesomeSubClass.self >>> case .whatever: return Whatever.self >>> case .etc: return Etc.self >>> } >>> } >>> } >>> var etc = Etc() >>> var className = ClassNames(etc) >>> var newEtc = className.type.init() >>> >>> The same trick works if all the types in question conform to the same >>> protocol, too: >>> protocol MyAwesomeProtocol { >>> init() >>> func toIntMax() -> IntMax >>> } >>> extension Int : MyAwesomeProtocol {} >>> struct Five : MyAwesomeProtocol { func toIntMax() -> IntMax { return 5 } } >>> enum ProtocolNames : String { >>> case five = "Five" >>> case int = "Int" >>> init(_ instance: MyAwesomeProtocol) { self = ProtocolNames.init(rawValue: >>> "\(type(of: instance))”)! } >>> init(_ type: MyAwesomeProtocol.Type) { self = >>> ProtocolNames.init(rawValue: "\(type)")! } >>> var type: MyAwesomeProtocol.Type { >>> switch self { >>> case .five: return Five.self >>> case .int: return Int.self >>> } >>> } >>> } >>> var five = Five() >>> var fiveName = ProtocolNames(five) >>> var newFive = fiveName.type.init() >>> >>> Either way, though, you’ll have to do something like if let nf = newFive >>> as? Int {…} if you want to use any functionality that isn’t explicitly in >>> the superclass or protocol. >>> >>> It certainly involves some boilerplate code, but it also has the advantages >>> of validating the name before you try to use it and ensuring that any >>> switch statements can actually handle all the classes. >>> >>> - Dave Sweeris >> >> >> -- >> Rick Mann >> rm...@latencyzero.com >> >> >> _______________________________________________ >> swift-users mailing list >> swift-users@swift.org >> https://lists.swift.org/mailman/listinfo/swift-users > -- Rick Mann rm...@latencyzero.com _______________________________________________ swift-users mailing list swift-users@swift.org https://lists.swift.org/mailman/listinfo/swift-users