Swift的面試問題及答案-part1

譯文:Swift Interview Questions and Answers

Swift面試問題及答案

原文鏈接 : Swift Interview Questions and Answers
譯文發(fā)布地址:
part1: http://www.lxweimin.com/p/e98d7dc625ff
part2:http://www.lxweimin.com/p/0b9bdffc2523
原文作者 : Antonio Bello
譯者 : lfb_CD 歡迎關注我的微博喲:http://weibo.com/lfbWb

雖然swift才發(fā)布不到一年的時間,但它已經(jīng)成為最流行的開發(fā)語言之一了。
事實上,Swift,是一種復雜的語言,同時面向?qū)ο蠛兔嫦蚝瘮?shù),并且它仍然還在不斷推出新的版本。

Swift有很多東西,但是你怎么能測試你學了多少?在這篇文章中,raywenderlich.com團隊和我一起列了一個列表-有關swift的面試問題。
你可以用這些問題來測試面試者的Swift知識,或者測試你自己的!如果你不知道答案,不要擔心,每一個問題都有一個答案。

問題分成了兩部分:

1.筆試題目(Written questions):可以通過電子郵件來進行編程測試,需要寫一些代碼。
2.口頭提問(Verbal questions):可以很好的在電話或面對面的面試中詢問,適用于口頭回答。

另外,每部分都分為三個等級:

  • 初級:適合初學者閱讀,已經(jīng)讀過一兩本有關Swift的書籍,并已經(jīng)在自己的應用程序使用了Swift。
  • 中級:適合某些對語言有濃厚興趣的人,閱讀過很多有關Swift的博客文章,并想進一步進行嘗試。
  • 高級:適合頂尖的-專注同時享受在程序語言里探索,挑戰(zhàn)自己,并使用尖端技術(shù)的人。

如果你想試著回答這些問題,建議你打開Playground。所有答案都已經(jīng)在Xcode 7 Beta 6中測試過。
準備好了嗎?Buckle up(系好安全帶?),開始了!

注:特別感謝團隊成員 Warren Burton, Greg Heo, Mikael Konutgan, Tim Mitra, Luke Parham, Rui Peres, and Ray Wenderlich

Written Questions(書面的問題)

Beginners(初學者)

你好,padowan(應該是指學徒,也就是我們。。)。我將開始檢測你的基本知識。

問題#1-Swift 1.0 or later

想有一個更好的方式來寫這里的循環(huán)范圍?

for var i = 0; i < 5; i++ {
    print("Hello!")
}
答案:
for i in 0...4 {
  print("Hello!")
}

Swift實現(xiàn)了二元操作符、閉區(qū)間操作符(...)和半閉區(qū)間操作符(..<)。第一個的范圍(...)包括所有的值。例如,下面包含所有的整數(shù),從0到4:

0...4

半閉區(qū)間操作符(..<)不包含最后一個元素。以下產(chǎn)生相同的0至4整數(shù)的結(jié)果:

0..<5

問題#2-Swift 1.0 or later

思考如下代碼:

struct Tutorial {
  var difficulty: Int = 1
}
var tutorial1 = Tutorial()
var tutorial2 = tutorial1
tutorial2.difficulty = 2

tutorial1.difficulty和tutorial2.difficulty的值是什么呢?如果是一個類,又是什么呢?為什么?

答案:

tutorial1.difficulty is 1,
tutorial2.difficulty is 2.
Swift的struct是值類型,它們被復制的是值,而不是引用。下面的代碼是創(chuàng)建一份tutorial1的拷貝并將其分配到tutorial2:

var tutorial2 = tutorial1

從這段代碼開始,對tutorial2任何改變都不會影響到tutorial1。
如果Tutorial是類,tutorial1.difficulty和tutorial2.difficulty都會是2。Swift的類是引用類型。對tutorial1屬性的任何變化會反映到tutorial2,反之亦然。

問題#3-Swift 1.0 or later

view1是用var聲明的,而view2是用let聲明的。這里的區(qū)別是什么,最后一行又可以編譯通過么?

import UIKit
var view1 = UIView()
view1.alpha = 0.5
let view2 = UIView()
view2.alpha = 0.5 // Will this line compile?
答案:

view1是一個變量,可以被重新分配到一個新的UIView的實例。用let你只可以賦值一次,所以這段的代碼不能編譯通過:

view2 = view1 // Error: view2 is immutable

但是,UIView是一個類的引用,所以你可以改變View2屬性(這意味著最后一行可以編譯通過):

let view2 = UIView()
view2.alpha = 0.5 // Yes!

問題#4-Swift 1.0 or later

下面這段代碼將數(shù)組按字母進行了排序,看起來很復雜,請盡可能的簡化它。

let animals = ["fish", "cat", "chicken", "dog"]
let sortedAnimals = animals.sort { (one: String, two: String) -> Bool in
  return one < two
}
答案:

先簡化參數(shù)。類型推導系統(tǒng)可以自動計算出閉包中的參數(shù)類型,所以我們可以去掉參數(shù):

let sortedAnimals = animals.sort { (one, two) -> Bool in return one < two }

返回值的類型也可以被推斷,所以扔掉它:

let sortedAnimals = animals.sort { (one, two) in return one < two }

符號$i可以代替參數(shù)名稱:

let sortedAnimals = animals.sort { return $0 < $1 }

在單語句閉包中,返回關鍵字可以省略。最后一個語句的返回值就是閉包的返回值:

let sortedAnimals = animals.sort { $0 < $1 }

這已經(jīng)很簡單了,但還不夠,不要停!
對于字符串,有一個比較函數(shù)定義如下:

func <(lhs: String, rhs: String) -> Bool

這個小功能使你的代碼更整潔:

let sortedAnimals = animals.sort(<)

注意,這里的每一步都是能編譯和輸出相同的結(jié)果的,并且你做了一個字符的閉包!

問題#5-Swift 1.0 or later

這段代碼創(chuàng)建了2個類、Address和Person,并且創(chuàng)建了2個實例來表示Ray和Brian。

class Address {
  var fullAddress: String
  var city: String 
  init(fullAddress: String, city: String) {
    self.fullAddress = fullAddress
    self.city = city
  }
}
class Person {
  var name: String
  var address: Address
  init(name: String, address: Address) {
    self.name = name
    self.address = address
  }
}
var headquarters = Address(fullAddress: "123 Tutorial Street", city: "Appletown")
var ray = Person(name: "Ray", address: headquarters)
var brian = Person(name: "Brian", address: headquarters)

假設brian搬到街對面的新大樓,所以你更新了他的地址:

brian.address.fullAddress = "148 Tutorial Street"

但是,仔細想一下這兒有什么問題,發(fā)生了什么?這是怎么回事?

答案:

Ray的address.fullAddress也跟著改變了!Address是一個類,并且具有引用的語義。headquarters是同一個實例,無論您訪問它通過Ray或Brian,改變headquarters的Address將改變它的兩個。
解決方案是重新分配給Brian一個新的Address,或設置Address為struct而不是class。

Intermediate(中級)

現(xiàn)在,開始挑戰(zhàn)困難點的問題。你準備好了嗎?

問題#1-Swift 2.0 or later

思考下列代碼:

var optional1: String? = nil
var optional2: String? = .None

nil和.None有什么區(qū)別?optional1和optional1變量有何不同?

答案:

其實沒有區(qū)別。Optional.None(.None是縮寫)是初始化一個可選變量(沒有值)的正確寫法,而不只是語法糖.None。
下面的驗證代碼的輸出是true:

nil == .None // On Swift 1.x this doesn't compile. You need Optional<Int>.None

請牢記,在底層下,optional是枚舉類型:

enum Optional<T> {
  case None
  case Some(T)
}

問題#2-Swift 1.0 or later

這是溫度計的模型,一個class和一個struct:

public class ThermometerClass {
  private(set) var temperature: Double = 0.0
  public func registerTemperature(temperature: Double) {
    self.temperature = temperature
  }
}
let thermometerClass = ThermometerClass()
thermometerClass.registerTemperature(56.0)
public struct ThermometerStruct {
  private(set) var temperature: Double = 0.0
  public mutating func registerTemperature(temperature: Double) {
    self.temperature = temperature
  }
} 
let thermometerStruct = ThermometerStruct()
thermometerStruct.registerTemperature(56.0)

這段代碼編譯出錯,請問哪里錯了?為什么錯了?

提示:仔細閱讀并思考一下,在Playground上測試它。

答案:

編譯器會在最后一行報錯。正確的thermometerstruct聲明與變異函數(shù)來改變其內(nèi)部的溫度變化,但編譯器報錯是因為registertemperature創(chuàng)建實例是通過let的,因此它是不變的。
在結(jié)構(gòu)體中,函數(shù)改變內(nèi)部狀態(tài)必須得是可變數(shù)據(jù)類型,即用var聲明的。

問題#3-Swift 1.0 or later

下面這段代碼會print出什么?為什么?

var thing = "cars"
let closure = { [thing] in
  print("I love \\(thing)")
}
thing = "airplanes"
closure()
答案:

它會打印“I love cars”。當閉包被聲明的時候,參數(shù)列表也會創(chuàng)建一份拷貝,所以參數(shù)的值不會改變,即使將一個新值賦值給一個。
如果在閉包中省略了參數(shù)列表([thing]),則編譯器將使用一個引用而不是復制。在這種情況下,當被調(diào)用時該變量的任何變化都會產(chǎn)生變化。如下面的代碼所示:
看不太懂就直接看代碼吧= =

var thing = "cars"
let closure = {    
  print("I love \\(thing)")
}
thing = "airplanes"
closure() // Prints "I love airplanes"

問題#4-Swift 2.0 or later

這里有一個全局函數(shù)來計算數(shù)組中 “值是唯一” 的數(shù)目:

func countUniques<T: Comparable>(array: Array<T>) -> Int {
  let sorted = array.sort(<)
  let initial: (T?, Int) = (.None, 0)
  let reduced = sorted.reduce(initial) { ($1, $0.0 == $1 ? $0.1 : $0.1 + 1) }
  return reduced.1
}

你可以這樣使用這個方法:

countUniques([1, 2, 3, 3]) // result is 3

請把這個函數(shù)重寫為數(shù)組的擴展方法,使得你可以按照下面代碼那樣使用:

[1, 2, 3, 3].countUniques() // should print 3
答案:

在Swift2.0中,泛型可以通過強制類型約束來進行擴展。如果泛型不滿足約束,則該擴展既不可見也不可訪問。

extension Array where Element: Comparable {
  func countUniques() -> Int {
    let sorted = sort(<)
    let initial: (Element?, Int) = (.None, 0)
    let reduced = sorted.reduce(initial) { ($1, $0.0 == $1 ? $0.1 : $0.1 + 1) }
    return reduced.1
  }
}

注意新方法只有在當前的數(shù)據(jù)類型實現(xiàn)了Comparable的協(xié)議時才可用。比如,如果你這樣調(diào)用的話編譯器會報錯:

import UIKit
let a = [UIView(), UIView()]
a.countUniques() // compiler error here because UIView doesn't implement Comparable

問題#5-Swift 2.0 or later

這里有一個函數(shù)來計算給定的兩個double的可選數(shù)據(jù)類型的除法。在執(zhí)行除法之前,需要滿足三個條件:

  • dividend不為空
  • divisor不為空
  • divisor不為0
func divide(dividend: Double?, by divisor: Double?) -> Double? {
  if dividend == .None {
    return .None
  }
  if divisor == .None {
    return .None
  }
  if divisor == 0 {
    return .None
  }
  return dividend! / divisor!
}

代碼雖然能工作,但有2個問題:

  • 它的條件可以guard語句
  • 它使用了強制拆包(那個!)不安全

請使用guard語句改進這個函數(shù),避免使用強制拆包。

答案:

如果條件不符合,新的guard語句在Swift2.0提供了返回值。檢查條件是非常有用的,因為它提供了一個清晰的方式表達方式--如果不需要對語句進行嵌套的話。這里就是一個例子:

guard dividend != .None else { return .None }

也可以結(jié)合可選數(shù)據(jù)類型,使得訪問變量在guard檢查之后:

guard let dividend = dividend else { return .None }

所以divide函數(shù)可以這樣寫:

func divide(dividend: Double?, by divisor: Double?) -> Double? {
  guard let dividend = dividend else { return .None }
  guard let divisor = divisor else { return .None }
  guard divisor != 0 else { return .None }
  return dividend / divisor
}

另外,你還可以合并guard語句,使函數(shù)看起來更簡單:

func divide(dividend: Double?, by divisor: Double?) -> Double? {
  guard let dividend = dividend, divisor = divisor where divisor != 0 else { return .None }
  return dividend / divisor
}

Advanced(高級)

問題#1-Swift 1.0 or later

思考下面的結(jié)構(gòu)體,一個溫度計的模型:

public struct Thermometer {
  public var temperature: Double
  public init(temperature: Double) {
    self.temperature = temperature
  }
}

創(chuàng)建一個實例,可以很容易地使用這個代碼:

var t: Thermometer = Thermometer(temperature:56.8)

但它有更好地初始化方式:

var thermometer: Thermometer = 56.8

怎么實現(xiàn)?

答案:

Swift定義了下面的協(xié)議,使用賦值操作符將一個類型的類型進行初始化:

  • NilLiteralConvertible
  • BooleanLiteralConvertible
  • IntegerLiteralConvertible
  • FloatLiteralConvertible
  • UnicodeScalarLiteralConvertible
  • ExtendedGraphemeClusterLiteralConvertible
  • StringLiteralConvertible
  • ArrayLiteralConvertible
  • DictionaryLiteralConvertible
    采用相應的協(xié)議,提供一個公共的初始化方法用來實現(xiàn)特定類型的文字初始化。在Thermometer下,實現(xiàn)FloatLiteralConvertible協(xié)議如下:
extension Thermometer : FloatLiteralConvertible {
  public init(floatLiteral value: FloatLiteralType) {
    self.init(temperature: value)
  }
}

現(xiàn)在你可以用一個簡單的浮點數(shù)據(jù)來創(chuàng)建一個實例。

var thermometer: Thermometer = 56.8

問題#2-Swift 1.0 or later

Swift擁有一組預定義的運算符,執(zhí)行不同類型的操作,例如算術(shù)或邏輯。它還允許創(chuàng)建自定義操作,一元或二元。

按照以下要求自定義并實現(xiàn)一個 ^^ 冪運算符:

  • 以兩個整數(shù)作為參數(shù)
  • 返回第一個參數(shù)與第二個參數(shù)的冪運算
  • 不用考慮潛在溢出錯誤
答案:

創(chuàng)建一個新的自定義操作符需要兩步:聲明和實現(xiàn)。
這部分我不太會翻譯,是關于自定義操作符的,這里有Swift的相關資料(http://www.yiibai.com/swift/custom_operators.html
這是聲明:

infix operator ^^ { associativity left precedence 155 }

實現(xiàn)的代碼如下:

import Foundation
func ^^(lhs: Int, rhs: Int) -> Int {
  let l = Double(lhs)
  let r = Double(rhs)
  let p = pow(l, r)
  return Int(p)
}

請注意,它沒有考慮溢出情況;如果操作產(chǎn)生的結(jié)果不能用int代表。比如大于int.max,會發(fā)生運行時錯誤。

問題#3-Swift 1.0 or later

你能用這樣的原始值來定義一個枚舉嗎?為什么?

enum Edges : (Double, Double) {
  case TopLeft = (0.0, 0.0)
  case TopRight = (1.0, 0.0)
  case BottomLeft = (0.0, 1.0)
  case BottomRight = (1.0, 1.0)
}
答案:

不能。一個原始值類型必須:

  • 符合合理的協(xié)議
  • 從下列任一個類型中轉(zhuǎn)換的:
    • Int
    • String
    • Character

在上面的代碼中,原始類型是一個元組,是不符合條件的。

問題#4-Swift 1.0 or later

考慮下面的代碼定義的Pizza結(jié)構(gòu)體和Pizza協(xié)議,以及擴展,包含有makemargherita()默認實現(xiàn)的一個方法:

struct Pizza {
  let ingredients: [String]
}
protocol Pizzeria {
  func makePizza(ingredients: [String]) -> Pizza
  func makeMargherita() -> Pizza
}
extension Pizzeria {
  func makeMargherita() -> Pizza {
    return makePizza(["tomato", "mozzarella"])
  }
}

現(xiàn)在餐廳Lombardis 的定義如下:

struct Lombardis: Pizzeria {
  func makePizza(ingredients: [String]) -> Pizza {
    return Pizza(ingredients: ingredients)
  }
  func makeMargherita() -> Pizza {
    return makePizza(["tomato", "basil", "mozzarella"])
  }
}

下面的代碼創(chuàng)建兩個Lombardis的實例。哪一個會成功調(diào)用margherita做出basil(一種面)?

let lombardis1: Pizzeria = Lombardis()
let lombardis2: Lombardis = Lombardis()
lombardis1.makeMargherita()
lombardis2.makeMargherita()
答案:

都能。Pizzeria協(xié)議聲明makemargherita()方法提供了一個默認的實現(xiàn)。該方法是在lombardis實現(xiàn)重寫。在這兩種情況下聲明的方法,在運行時都能正確執(zhí)行。
如果協(xié)議沒有聲明makemargherita()方法,但在擴展中還提供了一個默認的實現(xiàn)呢?

protocol Pizzeria {
  func makePizza(ingredients: [String]) -> Pizza
} 
extension Pizzeria {
  func makeMargherita() -> Pizza {
    return makePizza(["tomato", "mozzarella"])
  }
}

在這種情況下,只有l(wèi)ombardis2做出Pizza,而lombardis1沒有做出Pizza,因為lombardis1會去使用在擴展中定義的makeMargherita方法方法。它沒有聲明makeMargherita方法,就不會去調(diào)用結(jié)構(gòu)體里面的那個makeMargherita方法。

問題#5-Swift 2.0 or later

以下代碼編譯時有錯誤。你能發(fā)現(xiàn)哪里出錯了么,為什么會發(fā)生錯誤?

struct Kitten {
} 
func showKitten(kitten: Kitten?) {
  guard let k = kitten else {
    print("There is no kitten")
  }
  print(k)
}

Hint: There are three ways to fix it.

答案:

else里面需要退出路徑,使用return,或者拋出一個異常或聲明這是一個@noreturn的方法。最簡單的解決方案是添加返回語句。

func showKitten(kitten: Kitten?) {
  guard let k = kitten else {
    print("There is no kitten")
    return
  }
  print(k)
}

添加拋出異常的方法。

enum KittenError: ErrorType {
  case NoKitten
}
struct Kitten {
}
func showKitten(kitten: Kitten?) throws {
  guard let k = kitten else {
    print("There is no kitten")
    throw KittenError.NoKitten
  }
  print(k)
}
try showKitten(nil)

最后一個方法,調(diào)用fatalerror()方法,表明這是一個@noreturn方法。

struct Kitten {
} 
func showKitten(kitten: Kitten?) {
  guard let k = kitten else {
    print("There is no kitten")
    fatalError()
  }
  print(k)
}

Verbal questions part2部分待譯。


第一次翻譯這么長的文章,也許會有翻譯錯誤的地方,大家可以在評論中幫忙指出。

另外,我在管理一個微信公眾號SwiftTips,每天發(fā)布一些Swift的文章什么的,歡迎關注

qrcode_for_gh_e36203f1d8d6_258.jpg
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,406評論 6 538
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 99,034評論 3 423
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 177,413評論 0 382
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,449評論 1 316
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,165評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,559評論 1 325
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,606評論 3 444
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,781評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,327評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 41,084評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,278評論 1 371
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,849評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,495評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,927評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,172評論 1 291
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,010評論 3 396
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,241評論 2 375

推薦閱讀更多精彩內(nèi)容

  • Swift語言至今誕生有一年多的時間了,已經(jīng)成為當前最流行語言之一。雖然它的語法簡單好用,但實際上Swift是一門...
    TedX閱讀 10,040評論 1 39
  • * 函數(shù)是用來完成特定任務的獨立的代碼塊。你給一個函數(shù)起一個合適的名字,用來標識函數(shù)做什么,并且當函數(shù)需要執(zhí)行的時...
    Windv587閱讀 230評論 0 0
  • 譯文:Swift Interview Questions and Answers Swift面試問題及答案-par...
    lfb_CD閱讀 3,504評論 6 51
  • 做一個項目,每個人都想做得好做的快,而要做到這你必須確認你所認可的最后期限是合情合理。利用你的目標地圖,你可以很輕...
    一只永不止步的龍閱讀 295評論 0 0
  • 不知不覺,長假已過。假期都干了些什么?好像除了睡和吃,沒有其他了。在此反思。 回顧自己所有的假期,仿佛都是一個樣子...
    Just_Do_It_bin閱讀 619評論 0 0