Skip to content

Instantly share code, notes, and snippets.

@el-hoshino
Created February 10, 2017 08:29
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save el-hoshino/97d6ae35999a9fbb60bcdadd0db459ee to your computer and use it in GitHub Desktop.
Save el-hoshino/97d6ae35999a9fbb60bcdadd0db459ee to your computer and use it in GitHub Desktop.
今更聞けない?Struct と Class の使い分け方(補足) ref: http://qiita.com/lovee/items/0bf5e663dd74983cc0d3
switch instance {
case is Data: //もちろん英語的な意味での「データ」
useStruct()
case is Object: //もちろん英語的な意味での「オブジェクト」
useClass()
case _:
fatalError("ちゃんと考えろ!")
}
import Foundation
protocol BankAccountDelegate: class {
func account(_ account: BankAccount, changePasswordTo newPassword: String) throws -> Int
func account(_ account: BankAccount, transfer amount: Int, to receiver: Int) throws
}
//class BankAccount {
struct BankAccount {
let id: Int
private(set) var hashedPassword: Int
private(set) weak var delegate: BankAccountDelegate?
init(id: Int, hashedPassword: Int, delegate: BankAccountDelegate) {
self.id = id
self.hashedPassword = hashedPassword
self.delegate = delegate
}
// func changePassword(to newPassword: String) {
mutating func changePassword(to newPassword: String) {
do {
guard let delegate = self.delegate else { throw NSError() }
let newHashedPassword = try delegate.account(self, changePasswordTo: newPassword)
self.hashedPassword = newHashedPassword
print("パスワード変更成功")
} catch {
print("パスワード変更失敗")
}
}
func transfer(_ amount: Int, to receiver: Int) {
do {
guard let delegate = self.delegate else { throw NSError() }
try delegate.account(self, transfer: amount, to: receiver)
print("送金成功")
} catch {
print("送金失敗")
}
}
}
//protocol LoverBecomable { }
protocol LoverBecomable: class { }
//struct Human {
class Human {
var name: String
var item: String?
var bankAccounts: [BankAccount] = []
// var lover: LoverBecomable?
weak var lover: LoverBecomable?
init(name: String) {
self.name = name
}
}
extension Human: LoverBecomable { }
//var ktanaka = Human(name: "田中賢治")
//var maki = Human(name: "西木野真姫")
let ktanaka = Human(name: "田中賢治")
let maki = Human(name: "西木野真姫")
ktanaka.lover = maki
maki.item = "Bikini"
//(ktanaka.lover as? Human)?.item // nil
//ktanaka.lover === maki // Error: Binary operator '===' cannot be applied
(ktanaka.lover as? Human)?.item // "Bikini"
ktanaka.lover === maki // true
class Bank {
fileprivate class Account {
let id: Int
var hashedPassword: Int
var balance: Int
init(id: Int, hashedPassword: Int, balance: Int) {
self.id = id
self.hashedPassword = hashedPassword
self.balance = balance
}
func accountInfo(from delegate: BankAccountDelegate) -> BankAccount {
return BankAccount(id: self.id, hashedPassword: self.hashedPassword, delegate: delegate)
}
}
private let hashSalt = "\(arc4random())"
fileprivate var accounts: [Int: Account] = [:]
fileprivate func createHash(for string: String) -> Int {
return (string + self.hashSalt).hash
}
}
extension Bank {
func issueAccount(password: String) -> BankAccount {
var id = Int(arc4random())
while self.accounts[id] != nil {
id = Int(arc4random())
}
let hashedPassword = self.createHash(for: password)
let account = Account(id: id, hashedPassword: hashedPassword, balance: 1_000_000)
self.accounts[id] = account
return account.accountInfo(from: self)
}
}
extension Bank: BankAccountDelegate {
func account(_ account: BankAccount, transfer amount: Int, to receiverID: Int) throws {
enum Error: Swift.Error {
case transfererNotFound(id: Int)
case invalidPassword
case balanceNotEnough(balance: Int)
case receiverNotExist(id: Int)
}
guard let transferer = self.accounts[account.id] else {
throw Error.transfererNotFound(id: account.id)
}
guard transferer.hashedPassword == account.hashedPassword else {
throw Error.invalidPassword
}
guard transferer.balance >= amount else {
throw Error.balanceNotEnough(balance: transferer.balance)
}
guard let receiver = self.accounts[receiverID] else {
throw Error.receiverNotExist(id: receiverID)
}
transferer.balance -= amount
receiver.balance += amount
}
func account(_ account: BankAccount, changePasswordTo newPassword: String) throws -> Int {
enum Error: Swift.Error {
case accountNotFound(id: Int)
case invalidPassword
}
guard let accountObject = self.accounts[account.id] else {
throw Error.accountNotFound(id: account.id)
}
guard accountObject.hashedPassword == account.hashedPassword else {
throw Error.invalidPassword
}
let newHashedPassword = self.createHash(for: newPassword)
accountObject.hashedPassword = newHashedPassword
return newHashedPassword
}
}
let someBank = Bank()
let tanakaAccount = someBank.issueAccount(password: "1234")
ktanaka.bankAccounts.append(tanakaAccount)
let amazonAccountID = someBank.issueAccount(password: "J7BJuGy8ks2T").id
ktanaka.bankAccounts[0].transfer(1000, to: amazonAccountID) // 送金成功
maki.bankAccounts.append(ktanaka.bankAccounts[0])
maki.bankAccounts[0].transfer(100_000, to: amazonAccountID) // 送金成功
ktanaka.bankAccounts[0].changePassword(to: "5678")
//maki.bankAccounts[0].transfer(500_000, to: amazonAccountID) // 送金成功!?
maki.bankAccounts[0].transfer(500_000, to: amazonAccountID) // 送金失敗!
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment