Внедрить универсальный метод в Swift - PullRequest
0 голосов
/ 25 апреля 2018

Я реализую протокол-ориентированный подход в 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 голосов
/ 25 апреля 2018

Я бы использовал что-то вроде ниже, чтобы иметь возможность использовать основные функции в одном месте.Вам понадобятся суперклассы для общих функций задач, для этого будет недостаточно протоколов.

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()
0 голосов
/ 26 января 2019

Проверьте это:

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

0 голосов
/ 25 апреля 2018

Если я правильно понял, вам нужен способ написать функцию, которая печатает имя конформера Eat, название еды и пищевую ценность еды.

Ваш текущий протокол Food не получилдостаточно информации о пищевой ценности пищи (кальций, калории, клетчатка).Вы должны отредактировать свой протокол:

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

и реализовать 2 новых свойства в конформерах Food.Вот пример:

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
...