> On Jun 29, 2017, at 10:59 PM, Mikhail Seriukov via swift-users > <swift-users@swift.org> wrote: > > Hello everyone, > In objc there is quite common pattern when we use a base class with a type > property and concrete subclasses where type is uniquely identifying the > subclass. > We can then safely put subclasses objects into an array and then safely > downcast them when needed. > This kind of behaviour is commonly used in data sources implementations. > > Like this: > > typedef NS_ENUM(NSUInteger, CellDecriptorType) { > CellDecriptorTypeUnknown, > CellDecriptorType1, > CellDecriptorType2 > }; > > @interface BaseCellDescriptor : NSObject > > @property (nonatomic, readonly) CellDecriptorType type; > @property (nonatomic, strong) id value; > > @end > > > @interface CellDescriptor1 : BaseCellDescriptor > @end > > @implementation CellDescriptor1 > > - (CellDecriptorType)type { > return CellDecriptorType1; > } > > - (NSString *)value { > return @"string value"; > } > > @end > > > @interface CellDescriptor2 : BaseCellDescriptor > @end > > @implementation CellDescriptor2 > > - (CellDecriptorType)type { > return CellDecriptorType2; > } > > - (NSNumber *)value { > return @42; > } > > @end > > And somewhere later we do: > > - (void)doWorkWithCellDescriptors:(NSArray<BaseCellDescriptor *> > *)descriptors { > for (BaseCellDescriptor *descriptor in descriptors) { > CellDecriptorType type = descriptor.type; > switch(type) { > case CellDecriptorType1: { > CellDescriptor1 *aDescriptor = (CellDescriptor1 *)descriptor; > NSString *value = aDescriptor.value; > // Do something with value > break; > } > case CellDecriptorType2: { > CellDescriptor2 *aDescriptor = (CellDescriptor2 *)descriptor; > NSNumber *value = aDescriptor.value; > // Do something with value > break; > } > case CellDecriptorTypeUnknown: > default: { > // Handle error > break; > } > } > } > } > > > I want to implement it swifty way. So the questions are: > 0. Is it a bad practice to use this pattern and how we can avoid it? > 1. Is it possible to avoid inheritance here and only use generic protocols > and how? > 2. Is it possible to avoid downcasting if using this pattern in swift? > > > I've found the solution that seems to be a good example in this project > https://github.com/xmartlabs/Eureka. > They maintain both inheritance hierarchy and protocol hierarchy.
If you have a fixed set of types here, and you want to switch over them in a type-safe way, the natural thing to do would be to use an enum with payloads: enum BaseCellDescriptor { case type1(CellDescriptor1) case type2(CellDescriptor2) } func doWorkWithCellDescriptors(_ descriptors: [BaseCellDescriptor]) { for descriptor in descriptors { switch descriptor { case .type1(let aDescriptor): // aDescriptor has type CellDescriptor1 here case .type2(let aDescriptor): // aDescriptor has type CellDescriptor2 here } } } -Joe _______________________________________________ swift-users mailing list swift-users@swift.org https://lists.swift.org/mailman/listinfo/swift-users