Swift中Shop协议对应ShopImpl类的方法实现疑问咨询
Shop协议实现思路与完整代码
核心问题解决
Shop是定义行为的协议,ShopImpl作为它的实现类,需要在内部定义内存存储结构来保存Product对象。由于Product的id是唯一标识,用[String: Product]字典存储是最优选择——通过id作为key,增删查操作效率高,且能天然保证id的唯一性。
完整实现代码
struct Product { let id: String; // 唯一标识符 let name: String; let producer: String; } protocol Shop { /// 向商店添加新产品 /// - 参数product: 要添加的产品 /// - 返回值: 如果已存在相同id的产品返回false,否则返回true func addNewProduct(product: Product) -> Bool /// 根据id删除产品 /// - 返回值: 如果存在该id的产品返回true,否则返回false func deleteProduct(id: String) -> Bool /// 返回包含指定字符串的最多10个产品名称 /// 如果有多个产品同名,格式为"<生产者> - <产品名>",否则直接返回"<产品名>" func listProductsByName(searchString: String) -> Set<String> /// 返回生产者名称包含指定字符串的最多10个产品名称,结果按生产者排序 func listProductsByProducer(searchString: String) -> [String] } class ShopImpl: Shop { // 私有字典存储产品,key为产品id,保证唯一性 private var products: [String: Product] = [:] func addNewProduct(product: Product) -> Bool { // 检查id是否已存在,存在则返回false guard products[product.id] == nil else { return false } // 不存在则添加到字典 products[product.id] = product return true } func deleteProduct(id: String) -> Bool { // 尝试删除指定id的产品,删除成功(原存在)返回true,否则返回false guard products.removeValue(forKey: id) != nil else { return false } return true } func listProductsByName(searchString: String) -> Set<String> { // 过滤出名称包含搜索字符串的产品 let filteredProducts = products.values.filter { $0.name.contains(searchString) } // 统计每个产品名称的出现次数,用于判断是否需要添加生产者前缀 var nameOccurrenceCount: [String: Int] = [:] for product in filteredProducts { nameOccurrenceCount[product.name, default: 0] += 1 } var result: Set<String> = [] for product in filteredProducts { // 最多返回10个结果 guard result.count < 10 else { break } if nameOccurrenceCount[product.name] ?? 0 > 1 { result.insert("\(product.producer) - \(product.name)") } else { result.insert(product.name) } } return result } func listProductsByProducer(searchString: String) -> [String] { // 过滤出生产者名称包含搜索字符串的产品 let filteredProducts = products.values.filter { $0.producer.contains(searchString) } // 按生产者名称排序 let sortedProducts = filteredProducts.sorted { $0.producer < $1.producer } // 提取产品名称,最多取10个 return sortedProducts.prefix(10).map { $0.name } } }
测试用例验证
执行以下测试代码可验证实现正确性,所有断言均会通过:
func test(lib: Shop) { assert(!lib.deleteProduct(id: "1")) assert(lib.addNewProduct(product: Product(id: "1", name: "1", producer: "Lex"))) assert(!lib.addNewProduct(product: Product(id: "1", name: "any name because we check id only", producer: "any producer"))) assert(lib.deleteProduct(id: "1")) assert(lib.addNewProduct(product: Product(id: "3", name: "Some Product3", producer: "Some Producer2"))) assert(lib.addNewProduct(product: Product(id: "4", name: "Some Product1", producer: "Some Producer3"))) assert(lib.addNewProduct(product: Product(id: "2", name: "Some Product2", producer: "Some Producer2"))) assert(lib.addNewProduct(product: Product(id: "1", name: "Some Product1", producer: "Some Producer1"))) assert(lib.addNewProduct(product: Product(id: "5", name: "Other Product5", producer: "Other Producer4"))) assert(lib.addNewProduct(product: Product(id: "6", name: "Other Product6", producer: "Other Producer4"))) assert(lib.addNewProduct(product: Product(id: "7", name: "Other Product7", producer: "Other Producer4"))) assert(lib.addNewProduct(product: Product(id: "8", name: "Other Product8", producer: "Other Producer4"))) assert(lib.addNewProduct(product: Product(id: "9", name: "Other Product9", producer: "Other Producer4"))) assert(lib.addNewProduct(product: Product(id: "10", name: "Other Product10", producer: "Other Producer4"))) assert(lib.addNewProduct(product: Product(id: "11", name: "Other Product11", producer: "Other Producer4"))) var byNames: Set<String> = lib.listProductsByName(searchString: "Product") assert(byNames.count == 10) byNames = lib.listProductsByName(searchString: "Some Product") assert(byNames.count == 4) assert(byNames.contains("Some Producer3 - Some Product1")) assert(byNames.contains("Some Product2")) assert(byNames.contains("Some Product3")) assert(!byNames.contains("Some Product1")) assert(byNames.contains("Some Producer1 - Some Product1")) var byProducer: [String] = lib.listProductsByProducer(searchString: "Producer") assert(byProducer.count == 10) byProducer = lib.listProductsByProducer(searchString: "Some Producer") assert(byProducer.count == 4) assert(byProducer[0] == "Some Product1") assert(byProducer[1] == "Some Product2" || byProducer[1] == "Some Product3") assert(byProducer[2] == "Some Product2" || byProducer[2] == "Some Product3") assert(byProducer[3] == "Some Product1") } test(lib: ShopImpl())
内容的提问来源于stack exchange,提问作者bowtie
相关产品推荐
相关产品推荐

