Инициализатор Swift с именем, отличным от класса? - PullRequest
0 голосов
/ 12 апреля 2019

Я думаю, что ответ "не делай этого", но здесь идет ... Подумайте:

class Enemy {
   var name: String
   var type: Int
   init(ofType: Int) {
       type=ofType
   }
}

У меня есть два типа врагов: friends = 0 и closeFriends = 1.Враги могут переключаться между ними в любое время.Итак:

var newEnemy = Enemy(ofType:.closeFriend)
newEnemy.name = "Bob"

и, возможно, когда-нибудь в будущем:

newEnemy.type = .friend

Но я нахожу этот синтаксис несколько непрозрачным.По той же причине, по которой лучше использовать enum вместо Int, ваши намерения станут более ясными, если вы создадите новые объекты, которые непосредственно представляют их тип, возможно:

var newEnemy = CloseFriend(withName:"Bob")

Обычно этотребует создания подкласса Friend и CloseFriend, но тогда нельзя просто превратить Friend в CloseFriend.

typealias кажется, что это может быть решением, я мог бы псевдоним Enemy to Friend и CloseFriend.Но это не добавляет новый init, который устанавливает type на основе псевдонима.Например, CloseFriend () должен установить тип равным 1 без необходимости его указания.Есть ли способ сделать это?

Ответы [ 2 ]

1 голос
/ 12 апреля 2019

Это довольно просто сделать с помощью функции, но я бы действительно советовал:

class Enemy {
    enum EnemyType: Int {
        case friend
        case closeFriend
    }

    var name: String
    var type: EnemyType

    init(type: EnemyType, name: String = "") {
        self.type = type
        self.name = name
    }
}

// let's make a function that looks like creating new object
func CloseFriend(name: String) -> Enemy {
    return Enemy(type: .closeFriend, name: name)
}

Такие «умные» вещи полностью разрушают читабельность вашего кода. Нет ничего более читабельного, чем писать:

Enemy(type: .closeFriend, name: "Bob")

Нет смысла сохранять несколько букв кода.

Конечно, вы можете создать фабричную функцию

extension Enemy {
    static func closeFriend(name: String) -> Enemy {
        return Enemy(type: .closeFriend, name: name)
    }
}

но неужели лучше позвонить:

Enemy.closeFriend(name: "Bob")

против

Enemy(type: .closeFriend, name: "Bob")

0 голосов
/ 13 апреля 2019

Что ж, если один и тот же человек превращается из друга в близкого друга, имеет смысл повторно использовать один и тот же экземпляр.Точно так же, как это происходит в реальной жизни, когда отношения между людьми меняются (вы не получите чей-то клон, если этот человек начинает ненавидеть вас и хочет уничтожить вас).

То, что вы могли бы улучшить, говоря архитектурно, это объединить «навыки» и тип врага.Например:

class Enemy {
    var name: String
    var traits: Traits

    enum Traits {
        case friend(FriendTraits)
        case closeFriend(CloseFriendTraits)
    }

    struct FriendTraits { ... }
    struct CloseFriendTraits { ... }
}

Таким образом, вы можете просто изменить тип, сохранив при этом другие атрибуты (и если вы разрабатываете игру, другие атрибуты могут быть важны).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...