Skip to content

Instantly share code, notes, and snippets.

@chchrn
Created September 21, 2019 15:12
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save chchrn/0eff4681bf1f9f5312ce7b862c168cc8 to your computer and use it in GitHub Desktop.
Save chchrn/0eff4681bf1f9f5312ce7b862c168cc8 to your computer and use it in GitHub Desktop.
import UIKit
// For my question about abstract mapping: https://stackoverflow.com/questions/57944086/how-to-use-a-variable-that-conforms-to-a-protocol-with-a-specific-associated-typ
// Abstract mapping
protocol Mapping {
associatedtype T
associatedtype R
func map(_ object:T) -> R
}
class AbstractMapping<TModel,TResult>: Mapping {
typealias T = TModel
typealias R = TResult
func map(_ object: TModel) -> TResult {
fatalError("map(_:) has not been implemented")
}
}
class ClosureMapping<TModel,TResult>: AbstractMapping<TModel,TResult> {
typealias Closure = (TModel) -> TResult
private let closure: Closure
init(closure: @escaping Closure) {
self.closure = closure
}
override func map(_ obj: TModel) -> TResult {
return self.closure(obj)
}
}
class Calculator<TMapping: Mapping, TModel, TResult: Numeric> where TMapping.T == TModel, TMapping.R == TResult {
private let mapping: TMapping
init(mapping: TMapping) {
self.mapping = mapping
}
func calc(objects: [TModel]) -> TResult {
let numbers = objects.map { (v: TModel) -> TResult in
return self.mapping.map(v)
}
let sum = numbers.reduce(0, +)
return sum
}
}
// User
class User {
private let purchase: Double
private let name: String
init(name: String, purchase: Double) {
self.name = name
self.purchase = purchase
}
func yearPurchases() -> Double {
return self.purchase * 12
}
func monthPurchases() -> Double {
return self.purchase
}
}
// User's mapping
class UserMonthPurchaseMapping: AbstractMapping<User,Double> {
override func map(_ user: User) -> Double {
return user.monthPurchases()
}
}
// Specific use of two types of mapping
typealias UserClosureMapping = ClosureMapping<User,Double>
let yearPurchaseMapping = UserClosureMapping { (user: User) -> Double in
user.yearPurchases()
}
let monthPurchaseMapping = UserMonthPurchaseMapping()
let yearCalc: Calculator<AbstractMapping<User,Double>, User, Double> = Calculator(mapping: yearPurchaseMapping)
let monthCalc: Calculator<AbstractMapping<User,Double>, User, Double> = Calculator(mapping: monthPurchaseMapping)
let users = [User(name: "1", purchase: 10), User(name:"2", purchase:20), User(name:"3", purchase:5)]
let sumYear = yearCalc.calc(objects: users)
let sumMonth = monthCalc.calc(objects: users)
print("sumYear: \(sumYear), sumMonth: \(sumMonth)")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment