在swift

时间:2018-04-25 04:02:05

标签: swift generics struct associated-types protocol-oriented

我在Swift中实现了面向协议的方法,如下面的代码所示。这个概念看起来很有趣,但我希望你能得到这个想法。对我来说问题是如何为重复的打印任务实现通用功能。谢谢你的进步。

protocol Food {
    var name: String { get }
}

struct Grass: Food {
    var name: String { return "Grass" }
    var calcium: Float!
}

struct Rice: Food {
    var name: String { return "Rice" }
    var calories: Float!
}

struct Insect: Food {
    var name: String { return "Insect" }
    var fiber: Float!
}

protocol Eat {
    associatedtype food: Food
    var name: String { get }
    var itsFood: food { get }
}

struct Cow: Eat {
    typealias food = Grass
    var name: String { return "Cow" }
    var itsFood: food {return food(calcium: 100)}
}

struct People: Eat {
    typealias food = Rice
    var name: String { return "People" }
    var itsFood: food {return food(calories: 1000)}
}

struct Reptile: Eat {
    typealias food = Insect
    var name: String { return "Reptile" }
    var itsFood: food {return food(fiber: 300)}
}

let cow = Cow()
print(cow.name)
print(cow.itsFood.name)
print(cow.itsFood.calcium)

let people = People()
print(people.name)
print(people.itsFood.name)
print(people.itsFood.calories)

let reptile = Reptile()
print(reptile.name)
print(reptile.itsFood.name)
print(reptile.itsFood.fiber)

3 个答案:

答案 0 :(得分:1)

如果我理解正确,你想要一种方法来编写一个函数,打印出Eat conformer的名字,食物名称和食物的营养价值。

您当前的Food协议没有获得有关食物营养价值(钙,卡路里,纤维)的足够信息。你应该编辑你的协议:

protocol Food {
    var name: String { get }
    var nutritionalValueName: String { get }
    var nutritionalValue: Float! { get }
}

Food构造函数中实现2个新属性。这是一个例子:

struct Grass: Food {
    var name: String { return "Grass" }
    var calcium: Float!

    var nutritionalValue: Float! { return calcium }
    var nutritionalValueName: String { return "Calcium" }
}

现在,您可以编写一个函数。请注意,由于Eat具有关联类型,因此无法直接将其用作参数类型,您需要引入通用参数T并将其约束为Eat

func printEat<T: Eat>(eat: T) {
    print(eat.name)
    print(eat.itsFood.name)
    print("\(eat.itsFood.nutritionalValueName): \(eat.itsFood.nutritionalValue!)")
}

功能正文非常明显。

您可以这样称呼它:

printEat(eat: Cow())
printEat(eat: People())
printEat(eat: Reptile())

输出:

Cow
Grass
Calcium: 100.0
People
Rice
Calories: 1000.0
Reptile
Insect
Fiber: 300.0

答案 1 :(得分:0)

我会使用类似下面的内容来在一个地方使用基本功能。你需要超级类来完成常见的任务功能,协议还不够。

class Food {
    var name: String? { return nil }
    var calcium: Float?
    var calories: Float?
    var fiber: Float?
}

class Grass: Food {
    override var name: String? { return "Grass" }
    init(_ calcium: Float) {
        super.init()
        self.calcium = calcium
    }
}

class Rice: Food {
    override var name: String? { return "Rice" }
    init(_ calories: Float) {
        super.init()
        self.calories = calories
    }
}

class Insect: Food {
    override var name: String? { return "Insect" }
    init(_ fiber: Float) {
        super.init()
        self.fiber = fiber
    }
}

protocol Eat {
    var name: String? { get }
    var itsFood: Food? { get }
    func printInfo()
}

class Animal: Eat {
    var name: String? { return "Cow" }
    var itsFood: Food? { return Food() }
    func printInfo() {
        print(name ?? "")
        print(itsFood?.name ?? "")
        print(itsFood?.calcium ?? 0)
    }
}

class Cow: Animal {
    override var name: String? { return "Cow" }
    override var itsFood: Grass {return Grass(100) }
}

class People: Animal {
    override var name: String? { return "People" }
    override var itsFood: Food {return Rice(1000)}
}

class Reptile: Animal {
    override var name: String? { return "Reptile" }
    override var itsFood: Food {return Insect(300)}
}

let cow = Cow()
cow.printInfo()

答案 2 :(得分:0)

看看这个:

struct Fruit {

let fruitName : String
let color : String
init(_ name: String,_ color: String) {
    self.fruitName = name
    self.color = color
}
}

    let fruit1 = Fruit("Apple", "Red")
    let fruit2 = Fruit("Grapes", "Green")

    let fruitStack = Stack<Fruit>()
    fruitStack.push(fruit1)
    fruitStack.push(fruit2)

    let fruitFfromStack = fruitStack.pop()
    print("Fruit popped from Stack, Name : \(String(describing: fruitFfromStack?.fruitName)) ,Color : \(String(describing: fruitFfromStack?.color))")
    let fruitFfromStack1 = fruitStack.pop()
    print("Fruit popped from Stack, Name : \(String(describing: fruitFfromStack1?.fruitName)) ,Color : \(String(describing: fruitFfromStack1?.color))")

https://reactcodes.blogspot.com/2019/01/generic-stack-implementation-with.html