Reputation: 9279
I think the answer is "don't do that", but here goes... Consider:
class Enemy {
var name: String
var type: Int
init(ofType: Int) {
type=ofType
}
}
I have two types of enemies, friends=0 and closeFriends=1. One's enemies might switch between these at any time. So:
var newEnemy = Enemy(ofType:.closeFriend)
newEnemy.name = "Bob"
and perhaps at some time in the future:
newEnemy.type = .friend
But I find this syntax somewhat opaque. For the same reason that it's better to use an enum
instead of an Int
, your intentions are much more clear if you make new objects that directly represent their type, perhaps:
var newEnemy = CloseFriend(withName:"Bob")
Normally this requires subclassing Friend and CloseFriend, but then one cannot simply turn a Friend into a CloseFriend.
typealias
seems like it might be a solution, I could alias Enemy to Friend and CloseFriend. But that doesn't add a new init that sets the type
based on the alias. For instance, CloseFriend() should set the type to 1 without it having to be specified. Is there a way to do that?
Upvotes: 0
Views: 401
Reputation: 32783
Well, if the same person becomes changes from a friend to a close friend, it makes perfect sense to reuse the same instance. Just like it would happen in the real life, when relationships between people change (you don't get someone's clone if that person starts hating you and wants to destroy you).
What you could improve, architecturally speaking, is to merge the "skills" and the type of the enemy. E.g.:
class Enemy {
var name: String
var traits: Traits
enum Traits {
case friend(FriendTraits)
case closeFriend(CloseFriendTraits)
}
struct FriendTraits { ... }
struct CloseFriendTraits { ... }
}
This way you can simply change the type, while preserving the other attributes (and if you're developing a game the other attributes might be important).
Upvotes: 0
Reputation: 130102
This is rather simple to do using a function but I would really advise against it:
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)
}
Such "smart" things completely destroy the readability of your code. There is nothing more readable than writing:
Enemy(type: .closeFriend, name: "Bob")
There is no reason to save a few letters of code.
Sure, you could create a factory function
extension Enemy {
static func closeFriend(name: String) -> Enemy {
return Enemy(type: .closeFriend, name: name)
}
}
but is it really better to call:
Enemy.closeFriend(name: "Bob")
vs
Enemy(type: .closeFriend, name: "Bob")
?
Upvotes: 1