Created
February 10, 2017 08:29
-
-
Save el-hoshino/97d6ae35999a9fbb60bcdadd0db459ee to your computer and use it in GitHub Desktop.
今更聞けない?Struct と Class の使い分け方(補足) ref: http://qiita.com/lovee/items/0bf5e663dd74983cc0d3
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
switch instance { | |
case is Data: //もちろん英語的な意味での「データ」 | |
useStruct() | |
case is Object: //もちろん英語的な意味での「オブジェクト」 | |
useClass() | |
case _: | |
fatalError("ちゃんと考えろ!") | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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