├── .gitbook
└── assets
│ ├── CollectionTypes_intro_2x.png
│ ├── CollectionTypes_intro_2x~dark.png
│ ├── UTF16_2x.png
│ ├── UTF16_2x~dark.png
│ ├── UTF8_2x.png
│ ├── UTF8_2x~dark.png
│ ├── UnicodeScalar_2x.png
│ ├── UnicodeScalar_2x~dark.png
│ ├── barcode_QR_2x.png
│ ├── barcode_QR_2x~dark.png
│ ├── barcode_UPC_2x.png
│ ├── barcode_UPC_2x~dark.png
│ ├── bitshiftSignedAddition_2x.png
│ ├── bitshiftSignedAddition_2x~dark.png
│ ├── bitshiftSignedFour_2x.png
│ ├── bitshiftSignedFour_2x~dark.png
│ ├── bitshiftSignedMinusFourValue_2x.png
│ ├── bitshiftSignedMinusFourValue_2x~dark.png
│ ├── bitshiftSignedMinusFour_2x.png
│ ├── bitshiftSignedMinusFour_2x~dark.png
│ ├── bitshiftSigned_2x.png
│ ├── bitshiftSigned_2x~dark.png
│ ├── bitshiftUnsigned_2x.png
│ ├── bitshiftUnsigned_2x~dark.png
│ ├── bitwiseAND_2x.png
│ ├── bitwiseAND_2x~dark.png
│ ├── bitwiseNOT_2x.png
│ ├── bitwiseNOT_2x~dark.png
│ ├── bitwiseOR_2x.png
│ ├── bitwiseOR_2x~dark.png
│ ├── bitwiseXOR_2x.png
│ ├── bitwiseXOR_2x~dark.png
│ ├── chessBoard_2x.png
│ ├── chessBoard_2x~dark.png
│ ├── closureReferenceCycle01_2x.png
│ ├── closureReferenceCycle01_2x~dark.png
│ ├── closureReferenceCycle02_2x.png
│ ├── closureReferenceCycle02_2x~dark.png
│ ├── computedProperties_2x.png
│ ├── computedProperties_2x~dark.png
│ ├── coordinateGraphComplex_2x.png
│ ├── coordinateGraphComplex_2x~dark.png
│ ├── coordinateGraphMedium_2x.png
│ ├── coordinateGraphMedium_2x~dark.png
│ ├── coordinateGraphSimple_2x.png
│ ├── coordinateGraphSimple_2x~dark.png
│ ├── cover_opensource.jpg
│ ├── initializerDelegation01_2x.png
│ ├── initializerDelegation01_2x~dark.png
│ ├── initializerDelegation02_2x.png
│ ├── initializerDelegation02_2x~dark.png
│ ├── initializersExample01_2x.png
│ ├── initializersExample01_2x~dark.png
│ ├── initializersExample02_2x.png
│ ├── initializersExample02_2x~dark.png
│ ├── initializersExample03_2x.png
│ ├── initializersExample03_2x~dark.png
│ ├── macro-ast-input@2x.png
│ ├── macro-ast-input~dark@2x.png
│ ├── macro-ast-original@2x.png
│ ├── macro-ast-original~dark@2x.png
│ ├── macro-ast-output@2x.png
│ ├── macro-ast-output~dark@2x.png
│ ├── macro-ast-result@2x.png
│ ├── macro-ast-result~dark@2x.png
│ ├── macro-expansion-full@2x.png
│ ├── macro-expansion-full~dark@2x.png
│ ├── macro-expansion@2x.png
│ ├── macro-expansion~dark@2x.png
│ ├── memory_increment_2x.png
│ ├── memory_increment_2x~dark.png
│ ├── memory_mapInPlace_2x.png
│ ├── memory_mapInPlace_2x~dark.png
│ ├── memory_map_2x.png
│ ├── memory_map_2x~dark.png
│ ├── memory_share_health_maria_2x.png
│ ├── memory_share_health_maria_2x~dark.png
│ ├── memory_share_health_oscar_2x.png
│ ├── memory_share_health_oscar_2x~dark.png
│ ├── memory_shopping_2x.png
│ ├── memory_shopping_2x~dark.png
│ ├── multilineStringWhitespace_2x.png
│ ├── multilineStringWhitespace_2x~dark.png
│ ├── overflowAddition_2x.png
│ ├── overflowAddition_2x~dark.png
│ ├── overflowSignedSubtraction_2x.png
│ ├── overflowSignedSubtraction_2x~dark.png
│ ├── overflowUnsignedSubtraction_2x.png
│ ├── overflowUnsignedSubtraction_2x~dark.png
│ ├── referenceCycle01_2x.png
│ ├── referenceCycle01_2x~dark.png
│ ├── referenceCycle02_2x.png
│ ├── referenceCycle02_2x~dark.png
│ ├── referenceCycle03_2x.png
│ ├── referenceCycle03_2x~dark.png
│ ├── remainderInteger_2x.png
│ ├── remainderInteger_2x~dark.png
│ ├── setEulerDiagram_2x.png
│ ├── setEulerDiagram_2x~dark.png
│ ├── setVennDiagram_2x.png
│ ├── setVennDiagram_2x~dark.png
│ ├── sharedStateClass_2x.png
│ ├── sharedStateClass_2x~dark.png
│ ├── sharedStateStruct_2x.png
│ ├── sharedStateStruct_2x~dark.png
│ ├── snakesAndLadders_2x.png
│ ├── snakesAndLadders_2x~dark.png
│ ├── stackPoppedOneString_2x.png
│ ├── stackPoppedOneString_2x~dark.png
│ ├── stackPushPop_2x.png
│ ├── stackPushPop_2x~dark.png
│ ├── stackPushedFourStrings_2x.png
│ ├── stackPushedFourStrings_2x~dark.png
│ ├── staticPropertiesVUMeter_2x.png
│ ├── staticPropertiesVUMeter_2x~dark.png
│ ├── stringSubstring_2x.png
│ ├── stringSubstring_2x~dark.png
│ ├── subscriptMatrix01_2x.png
│ ├── subscriptMatrix01_2x~dark.png
│ ├── subscriptMatrix02_2x.png
│ ├── subscriptMatrix02_2x~dark.png
│ ├── twoPhaseInitialization01_2x.png
│ ├── twoPhaseInitialization01_2x~dark.png
│ ├── twoPhaseInitialization02_2x.png
│ ├── twoPhaseInitialization02_2x~dark.png
│ ├── unownedOptionalReference_2x.png
│ ├── unownedOptionalReference_2x~dark.png
│ ├── unownedReference01_2x.png
│ ├── unownedReference01_2x~dark.png
│ ├── unownedReference02_2x.png
│ ├── unownedReference02_2x~dark.png
│ ├── vectorAddition_2x.png
│ ├── vectorAddition_2x~dark.png
│ ├── weakReference01_2x.png
│ ├── weakReference01_2x~dark.png
│ ├── weakReference02_2x.png
│ ├── weakReference02_2x~dark.png
│ ├── weakReference03_2x.png
│ └── weakReference03_2x~dark.png
├── .gitignore
├── README.md
├── SUMMARY.md
├── contact
└── undefined.md
├── language-guide-1
├── access-control.md
├── advanced-operators.md
├── automatic-reference-counting.md
├── basic-operators.md
├── closures.md
├── collection-types.md
├── concurrency.md
├── control-flow.md
├── deinitialization.md
├── enumerations.md
├── error-handling.md
├── extensions.md
├── functions.md
├── generics.md
├── inheritance.md
├── initialization.md
├── macros.md
├── memory-safety.md
├── methods.md
├── nested-types.md
├── opaque-types.md
├── optional-chaining.md
├── properties.md
├── protocols.md
├── strings-and-characters.md
├── structures-and-classes.md
├── subscripts.md
├── the-basics.md
└── type-casting.md
├── language-reference
├── about-the-language-reference.md
├── attributes.md
├── declarations.md
├── expressions.md
├── generic-parameters-and-arguments.md
├── lexical-structure.md
├── patterns.md
├── statements.md
├── summary-of-the-grammar.md
└── types.md
├── revision-history
└── document-revision-history.md
└── welcome-to-swift
├── swift-a-swift-tour.md
├── swift-about-swift.md
└── version-compatibility.md
/.gitbook/assets/CollectionTypes_intro_2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bbiguduk/Swift_language_guide_kr/6d2a3ab844d345a6db5e37263bce1d8fa8547b4a/.gitbook/assets/CollectionTypes_intro_2x.png
--------------------------------------------------------------------------------
/.gitbook/assets/CollectionTypes_intro_2x~dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bbiguduk/Swift_language_guide_kr/6d2a3ab844d345a6db5e37263bce1d8fa8547b4a/.gitbook/assets/CollectionTypes_intro_2x~dark.png
--------------------------------------------------------------------------------
/.gitbook/assets/UTF16_2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bbiguduk/Swift_language_guide_kr/6d2a3ab844d345a6db5e37263bce1d8fa8547b4a/.gitbook/assets/UTF16_2x.png
--------------------------------------------------------------------------------
/.gitbook/assets/UTF16_2x~dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bbiguduk/Swift_language_guide_kr/6d2a3ab844d345a6db5e37263bce1d8fa8547b4a/.gitbook/assets/UTF16_2x~dark.png
--------------------------------------------------------------------------------
/.gitbook/assets/UTF8_2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bbiguduk/Swift_language_guide_kr/6d2a3ab844d345a6db5e37263bce1d8fa8547b4a/.gitbook/assets/UTF8_2x.png
--------------------------------------------------------------------------------
/.gitbook/assets/UTF8_2x~dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bbiguduk/Swift_language_guide_kr/6d2a3ab844d345a6db5e37263bce1d8fa8547b4a/.gitbook/assets/UTF8_2x~dark.png
--------------------------------------------------------------------------------
/.gitbook/assets/UnicodeScalar_2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bbiguduk/Swift_language_guide_kr/6d2a3ab844d345a6db5e37263bce1d8fa8547b4a/.gitbook/assets/UnicodeScalar_2x.png
--------------------------------------------------------------------------------
/.gitbook/assets/UnicodeScalar_2x~dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bbiguduk/Swift_language_guide_kr/6d2a3ab844d345a6db5e37263bce1d8fa8547b4a/.gitbook/assets/UnicodeScalar_2x~dark.png
--------------------------------------------------------------------------------
/.gitbook/assets/barcode_QR_2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bbiguduk/Swift_language_guide_kr/6d2a3ab844d345a6db5e37263bce1d8fa8547b4a/.gitbook/assets/barcode_QR_2x.png
--------------------------------------------------------------------------------
/.gitbook/assets/barcode_QR_2x~dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bbiguduk/Swift_language_guide_kr/6d2a3ab844d345a6db5e37263bce1d8fa8547b4a/.gitbook/assets/barcode_QR_2x~dark.png
--------------------------------------------------------------------------------
/.gitbook/assets/barcode_UPC_2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bbiguduk/Swift_language_guide_kr/6d2a3ab844d345a6db5e37263bce1d8fa8547b4a/.gitbook/assets/barcode_UPC_2x.png
--------------------------------------------------------------------------------
/.gitbook/assets/barcode_UPC_2x~dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bbiguduk/Swift_language_guide_kr/6d2a3ab844d345a6db5e37263bce1d8fa8547b4a/.gitbook/assets/barcode_UPC_2x~dark.png
--------------------------------------------------------------------------------
/.gitbook/assets/bitshiftSignedAddition_2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bbiguduk/Swift_language_guide_kr/6d2a3ab844d345a6db5e37263bce1d8fa8547b4a/.gitbook/assets/bitshiftSignedAddition_2x.png
--------------------------------------------------------------------------------
/.gitbook/assets/bitshiftSignedAddition_2x~dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bbiguduk/Swift_language_guide_kr/6d2a3ab844d345a6db5e37263bce1d8fa8547b4a/.gitbook/assets/bitshiftSignedAddition_2x~dark.png
--------------------------------------------------------------------------------
/.gitbook/assets/bitshiftSignedFour_2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bbiguduk/Swift_language_guide_kr/6d2a3ab844d345a6db5e37263bce1d8fa8547b4a/.gitbook/assets/bitshiftSignedFour_2x.png
--------------------------------------------------------------------------------
/.gitbook/assets/bitshiftSignedFour_2x~dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bbiguduk/Swift_language_guide_kr/6d2a3ab844d345a6db5e37263bce1d8fa8547b4a/.gitbook/assets/bitshiftSignedFour_2x~dark.png
--------------------------------------------------------------------------------
/.gitbook/assets/bitshiftSignedMinusFourValue_2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bbiguduk/Swift_language_guide_kr/6d2a3ab844d345a6db5e37263bce1d8fa8547b4a/.gitbook/assets/bitshiftSignedMinusFourValue_2x.png
--------------------------------------------------------------------------------
/.gitbook/assets/bitshiftSignedMinusFourValue_2x~dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bbiguduk/Swift_language_guide_kr/6d2a3ab844d345a6db5e37263bce1d8fa8547b4a/.gitbook/assets/bitshiftSignedMinusFourValue_2x~dark.png
--------------------------------------------------------------------------------
/.gitbook/assets/bitshiftSignedMinusFour_2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bbiguduk/Swift_language_guide_kr/6d2a3ab844d345a6db5e37263bce1d8fa8547b4a/.gitbook/assets/bitshiftSignedMinusFour_2x.png
--------------------------------------------------------------------------------
/.gitbook/assets/bitshiftSignedMinusFour_2x~dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bbiguduk/Swift_language_guide_kr/6d2a3ab844d345a6db5e37263bce1d8fa8547b4a/.gitbook/assets/bitshiftSignedMinusFour_2x~dark.png
--------------------------------------------------------------------------------
/.gitbook/assets/bitshiftSigned_2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bbiguduk/Swift_language_guide_kr/6d2a3ab844d345a6db5e37263bce1d8fa8547b4a/.gitbook/assets/bitshiftSigned_2x.png
--------------------------------------------------------------------------------
/.gitbook/assets/bitshiftSigned_2x~dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bbiguduk/Swift_language_guide_kr/6d2a3ab844d345a6db5e37263bce1d8fa8547b4a/.gitbook/assets/bitshiftSigned_2x~dark.png
--------------------------------------------------------------------------------
/.gitbook/assets/bitshiftUnsigned_2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bbiguduk/Swift_language_guide_kr/6d2a3ab844d345a6db5e37263bce1d8fa8547b4a/.gitbook/assets/bitshiftUnsigned_2x.png
--------------------------------------------------------------------------------
/.gitbook/assets/bitshiftUnsigned_2x~dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bbiguduk/Swift_language_guide_kr/6d2a3ab844d345a6db5e37263bce1d8fa8547b4a/.gitbook/assets/bitshiftUnsigned_2x~dark.png
--------------------------------------------------------------------------------
/.gitbook/assets/bitwiseAND_2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bbiguduk/Swift_language_guide_kr/6d2a3ab844d345a6db5e37263bce1d8fa8547b4a/.gitbook/assets/bitwiseAND_2x.png
--------------------------------------------------------------------------------
/.gitbook/assets/bitwiseAND_2x~dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bbiguduk/Swift_language_guide_kr/6d2a3ab844d345a6db5e37263bce1d8fa8547b4a/.gitbook/assets/bitwiseAND_2x~dark.png
--------------------------------------------------------------------------------
/.gitbook/assets/bitwiseNOT_2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bbiguduk/Swift_language_guide_kr/6d2a3ab844d345a6db5e37263bce1d8fa8547b4a/.gitbook/assets/bitwiseNOT_2x.png
--------------------------------------------------------------------------------
/.gitbook/assets/bitwiseNOT_2x~dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bbiguduk/Swift_language_guide_kr/6d2a3ab844d345a6db5e37263bce1d8fa8547b4a/.gitbook/assets/bitwiseNOT_2x~dark.png
--------------------------------------------------------------------------------
/.gitbook/assets/bitwiseOR_2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bbiguduk/Swift_language_guide_kr/6d2a3ab844d345a6db5e37263bce1d8fa8547b4a/.gitbook/assets/bitwiseOR_2x.png
--------------------------------------------------------------------------------
/.gitbook/assets/bitwiseOR_2x~dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bbiguduk/Swift_language_guide_kr/6d2a3ab844d345a6db5e37263bce1d8fa8547b4a/.gitbook/assets/bitwiseOR_2x~dark.png
--------------------------------------------------------------------------------
/.gitbook/assets/bitwiseXOR_2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bbiguduk/Swift_language_guide_kr/6d2a3ab844d345a6db5e37263bce1d8fa8547b4a/.gitbook/assets/bitwiseXOR_2x.png
--------------------------------------------------------------------------------
/.gitbook/assets/bitwiseXOR_2x~dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bbiguduk/Swift_language_guide_kr/6d2a3ab844d345a6db5e37263bce1d8fa8547b4a/.gitbook/assets/bitwiseXOR_2x~dark.png
--------------------------------------------------------------------------------
/.gitbook/assets/chessBoard_2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bbiguduk/Swift_language_guide_kr/6d2a3ab844d345a6db5e37263bce1d8fa8547b4a/.gitbook/assets/chessBoard_2x.png
--------------------------------------------------------------------------------
/.gitbook/assets/chessBoard_2x~dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bbiguduk/Swift_language_guide_kr/6d2a3ab844d345a6db5e37263bce1d8fa8547b4a/.gitbook/assets/chessBoard_2x~dark.png
--------------------------------------------------------------------------------
/.gitbook/assets/closureReferenceCycle01_2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bbiguduk/Swift_language_guide_kr/6d2a3ab844d345a6db5e37263bce1d8fa8547b4a/.gitbook/assets/closureReferenceCycle01_2x.png
--------------------------------------------------------------------------------
/.gitbook/assets/closureReferenceCycle01_2x~dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bbiguduk/Swift_language_guide_kr/6d2a3ab844d345a6db5e37263bce1d8fa8547b4a/.gitbook/assets/closureReferenceCycle01_2x~dark.png
--------------------------------------------------------------------------------
/.gitbook/assets/closureReferenceCycle02_2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bbiguduk/Swift_language_guide_kr/6d2a3ab844d345a6db5e37263bce1d8fa8547b4a/.gitbook/assets/closureReferenceCycle02_2x.png
--------------------------------------------------------------------------------
/.gitbook/assets/closureReferenceCycle02_2x~dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bbiguduk/Swift_language_guide_kr/6d2a3ab844d345a6db5e37263bce1d8fa8547b4a/.gitbook/assets/closureReferenceCycle02_2x~dark.png
--------------------------------------------------------------------------------
/.gitbook/assets/computedProperties_2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bbiguduk/Swift_language_guide_kr/6d2a3ab844d345a6db5e37263bce1d8fa8547b4a/.gitbook/assets/computedProperties_2x.png
--------------------------------------------------------------------------------
/.gitbook/assets/computedProperties_2x~dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bbiguduk/Swift_language_guide_kr/6d2a3ab844d345a6db5e37263bce1d8fa8547b4a/.gitbook/assets/computedProperties_2x~dark.png
--------------------------------------------------------------------------------
/.gitbook/assets/coordinateGraphComplex_2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bbiguduk/Swift_language_guide_kr/6d2a3ab844d345a6db5e37263bce1d8fa8547b4a/.gitbook/assets/coordinateGraphComplex_2x.png
--------------------------------------------------------------------------------
/.gitbook/assets/coordinateGraphComplex_2x~dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bbiguduk/Swift_language_guide_kr/6d2a3ab844d345a6db5e37263bce1d8fa8547b4a/.gitbook/assets/coordinateGraphComplex_2x~dark.png
--------------------------------------------------------------------------------
/.gitbook/assets/coordinateGraphMedium_2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bbiguduk/Swift_language_guide_kr/6d2a3ab844d345a6db5e37263bce1d8fa8547b4a/.gitbook/assets/coordinateGraphMedium_2x.png
--------------------------------------------------------------------------------
/.gitbook/assets/coordinateGraphMedium_2x~dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bbiguduk/Swift_language_guide_kr/6d2a3ab844d345a6db5e37263bce1d8fa8547b4a/.gitbook/assets/coordinateGraphMedium_2x~dark.png
--------------------------------------------------------------------------------
/.gitbook/assets/coordinateGraphSimple_2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bbiguduk/Swift_language_guide_kr/6d2a3ab844d345a6db5e37263bce1d8fa8547b4a/.gitbook/assets/coordinateGraphSimple_2x.png
--------------------------------------------------------------------------------
/.gitbook/assets/coordinateGraphSimple_2x~dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bbiguduk/Swift_language_guide_kr/6d2a3ab844d345a6db5e37263bce1d8fa8547b4a/.gitbook/assets/coordinateGraphSimple_2x~dark.png
--------------------------------------------------------------------------------
/.gitbook/assets/cover_opensource.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bbiguduk/Swift_language_guide_kr/6d2a3ab844d345a6db5e37263bce1d8fa8547b4a/.gitbook/assets/cover_opensource.jpg
--------------------------------------------------------------------------------
/.gitbook/assets/initializerDelegation01_2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bbiguduk/Swift_language_guide_kr/6d2a3ab844d345a6db5e37263bce1d8fa8547b4a/.gitbook/assets/initializerDelegation01_2x.png
--------------------------------------------------------------------------------
/.gitbook/assets/initializerDelegation01_2x~dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bbiguduk/Swift_language_guide_kr/6d2a3ab844d345a6db5e37263bce1d8fa8547b4a/.gitbook/assets/initializerDelegation01_2x~dark.png
--------------------------------------------------------------------------------
/.gitbook/assets/initializerDelegation02_2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bbiguduk/Swift_language_guide_kr/6d2a3ab844d345a6db5e37263bce1d8fa8547b4a/.gitbook/assets/initializerDelegation02_2x.png
--------------------------------------------------------------------------------
/.gitbook/assets/initializerDelegation02_2x~dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bbiguduk/Swift_language_guide_kr/6d2a3ab844d345a6db5e37263bce1d8fa8547b4a/.gitbook/assets/initializerDelegation02_2x~dark.png
--------------------------------------------------------------------------------
/.gitbook/assets/initializersExample01_2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bbiguduk/Swift_language_guide_kr/6d2a3ab844d345a6db5e37263bce1d8fa8547b4a/.gitbook/assets/initializersExample01_2x.png
--------------------------------------------------------------------------------
/.gitbook/assets/initializersExample01_2x~dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bbiguduk/Swift_language_guide_kr/6d2a3ab844d345a6db5e37263bce1d8fa8547b4a/.gitbook/assets/initializersExample01_2x~dark.png
--------------------------------------------------------------------------------
/.gitbook/assets/initializersExample02_2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bbiguduk/Swift_language_guide_kr/6d2a3ab844d345a6db5e37263bce1d8fa8547b4a/.gitbook/assets/initializersExample02_2x.png
--------------------------------------------------------------------------------
/.gitbook/assets/initializersExample02_2x~dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bbiguduk/Swift_language_guide_kr/6d2a3ab844d345a6db5e37263bce1d8fa8547b4a/.gitbook/assets/initializersExample02_2x~dark.png
--------------------------------------------------------------------------------
/.gitbook/assets/initializersExample03_2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bbiguduk/Swift_language_guide_kr/6d2a3ab844d345a6db5e37263bce1d8fa8547b4a/.gitbook/assets/initializersExample03_2x.png
--------------------------------------------------------------------------------
/.gitbook/assets/initializersExample03_2x~dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bbiguduk/Swift_language_guide_kr/6d2a3ab844d345a6db5e37263bce1d8fa8547b4a/.gitbook/assets/initializersExample03_2x~dark.png
--------------------------------------------------------------------------------
/.gitbook/assets/macro-ast-input@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bbiguduk/Swift_language_guide_kr/6d2a3ab844d345a6db5e37263bce1d8fa8547b4a/.gitbook/assets/macro-ast-input@2x.png
--------------------------------------------------------------------------------
/.gitbook/assets/macro-ast-input~dark@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bbiguduk/Swift_language_guide_kr/6d2a3ab844d345a6db5e37263bce1d8fa8547b4a/.gitbook/assets/macro-ast-input~dark@2x.png
--------------------------------------------------------------------------------
/.gitbook/assets/macro-ast-original@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bbiguduk/Swift_language_guide_kr/6d2a3ab844d345a6db5e37263bce1d8fa8547b4a/.gitbook/assets/macro-ast-original@2x.png
--------------------------------------------------------------------------------
/.gitbook/assets/macro-ast-original~dark@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bbiguduk/Swift_language_guide_kr/6d2a3ab844d345a6db5e37263bce1d8fa8547b4a/.gitbook/assets/macro-ast-original~dark@2x.png
--------------------------------------------------------------------------------
/.gitbook/assets/macro-ast-output@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bbiguduk/Swift_language_guide_kr/6d2a3ab844d345a6db5e37263bce1d8fa8547b4a/.gitbook/assets/macro-ast-output@2x.png
--------------------------------------------------------------------------------
/.gitbook/assets/macro-ast-output~dark@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bbiguduk/Swift_language_guide_kr/6d2a3ab844d345a6db5e37263bce1d8fa8547b4a/.gitbook/assets/macro-ast-output~dark@2x.png
--------------------------------------------------------------------------------
/.gitbook/assets/macro-ast-result@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bbiguduk/Swift_language_guide_kr/6d2a3ab844d345a6db5e37263bce1d8fa8547b4a/.gitbook/assets/macro-ast-result@2x.png
--------------------------------------------------------------------------------
/.gitbook/assets/macro-ast-result~dark@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bbiguduk/Swift_language_guide_kr/6d2a3ab844d345a6db5e37263bce1d8fa8547b4a/.gitbook/assets/macro-ast-result~dark@2x.png
--------------------------------------------------------------------------------
/.gitbook/assets/macro-expansion-full@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bbiguduk/Swift_language_guide_kr/6d2a3ab844d345a6db5e37263bce1d8fa8547b4a/.gitbook/assets/macro-expansion-full@2x.png
--------------------------------------------------------------------------------
/.gitbook/assets/macro-expansion-full~dark@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bbiguduk/Swift_language_guide_kr/6d2a3ab844d345a6db5e37263bce1d8fa8547b4a/.gitbook/assets/macro-expansion-full~dark@2x.png
--------------------------------------------------------------------------------
/.gitbook/assets/macro-expansion@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bbiguduk/Swift_language_guide_kr/6d2a3ab844d345a6db5e37263bce1d8fa8547b4a/.gitbook/assets/macro-expansion@2x.png
--------------------------------------------------------------------------------
/.gitbook/assets/macro-expansion~dark@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bbiguduk/Swift_language_guide_kr/6d2a3ab844d345a6db5e37263bce1d8fa8547b4a/.gitbook/assets/macro-expansion~dark@2x.png
--------------------------------------------------------------------------------
/.gitbook/assets/memory_increment_2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bbiguduk/Swift_language_guide_kr/6d2a3ab844d345a6db5e37263bce1d8fa8547b4a/.gitbook/assets/memory_increment_2x.png
--------------------------------------------------------------------------------
/.gitbook/assets/memory_increment_2x~dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bbiguduk/Swift_language_guide_kr/6d2a3ab844d345a6db5e37263bce1d8fa8547b4a/.gitbook/assets/memory_increment_2x~dark.png
--------------------------------------------------------------------------------
/.gitbook/assets/memory_mapInPlace_2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bbiguduk/Swift_language_guide_kr/6d2a3ab844d345a6db5e37263bce1d8fa8547b4a/.gitbook/assets/memory_mapInPlace_2x.png
--------------------------------------------------------------------------------
/.gitbook/assets/memory_mapInPlace_2x~dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bbiguduk/Swift_language_guide_kr/6d2a3ab844d345a6db5e37263bce1d8fa8547b4a/.gitbook/assets/memory_mapInPlace_2x~dark.png
--------------------------------------------------------------------------------
/.gitbook/assets/memory_map_2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bbiguduk/Swift_language_guide_kr/6d2a3ab844d345a6db5e37263bce1d8fa8547b4a/.gitbook/assets/memory_map_2x.png
--------------------------------------------------------------------------------
/.gitbook/assets/memory_map_2x~dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bbiguduk/Swift_language_guide_kr/6d2a3ab844d345a6db5e37263bce1d8fa8547b4a/.gitbook/assets/memory_map_2x~dark.png
--------------------------------------------------------------------------------
/.gitbook/assets/memory_share_health_maria_2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bbiguduk/Swift_language_guide_kr/6d2a3ab844d345a6db5e37263bce1d8fa8547b4a/.gitbook/assets/memory_share_health_maria_2x.png
--------------------------------------------------------------------------------
/.gitbook/assets/memory_share_health_maria_2x~dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bbiguduk/Swift_language_guide_kr/6d2a3ab844d345a6db5e37263bce1d8fa8547b4a/.gitbook/assets/memory_share_health_maria_2x~dark.png
--------------------------------------------------------------------------------
/.gitbook/assets/memory_share_health_oscar_2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bbiguduk/Swift_language_guide_kr/6d2a3ab844d345a6db5e37263bce1d8fa8547b4a/.gitbook/assets/memory_share_health_oscar_2x.png
--------------------------------------------------------------------------------
/.gitbook/assets/memory_share_health_oscar_2x~dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bbiguduk/Swift_language_guide_kr/6d2a3ab844d345a6db5e37263bce1d8fa8547b4a/.gitbook/assets/memory_share_health_oscar_2x~dark.png
--------------------------------------------------------------------------------
/.gitbook/assets/memory_shopping_2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bbiguduk/Swift_language_guide_kr/6d2a3ab844d345a6db5e37263bce1d8fa8547b4a/.gitbook/assets/memory_shopping_2x.png
--------------------------------------------------------------------------------
/.gitbook/assets/memory_shopping_2x~dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bbiguduk/Swift_language_guide_kr/6d2a3ab844d345a6db5e37263bce1d8fa8547b4a/.gitbook/assets/memory_shopping_2x~dark.png
--------------------------------------------------------------------------------
/.gitbook/assets/multilineStringWhitespace_2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bbiguduk/Swift_language_guide_kr/6d2a3ab844d345a6db5e37263bce1d8fa8547b4a/.gitbook/assets/multilineStringWhitespace_2x.png
--------------------------------------------------------------------------------
/.gitbook/assets/multilineStringWhitespace_2x~dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bbiguduk/Swift_language_guide_kr/6d2a3ab844d345a6db5e37263bce1d8fa8547b4a/.gitbook/assets/multilineStringWhitespace_2x~dark.png
--------------------------------------------------------------------------------
/.gitbook/assets/overflowAddition_2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bbiguduk/Swift_language_guide_kr/6d2a3ab844d345a6db5e37263bce1d8fa8547b4a/.gitbook/assets/overflowAddition_2x.png
--------------------------------------------------------------------------------
/.gitbook/assets/overflowAddition_2x~dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bbiguduk/Swift_language_guide_kr/6d2a3ab844d345a6db5e37263bce1d8fa8547b4a/.gitbook/assets/overflowAddition_2x~dark.png
--------------------------------------------------------------------------------
/.gitbook/assets/overflowSignedSubtraction_2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bbiguduk/Swift_language_guide_kr/6d2a3ab844d345a6db5e37263bce1d8fa8547b4a/.gitbook/assets/overflowSignedSubtraction_2x.png
--------------------------------------------------------------------------------
/.gitbook/assets/overflowSignedSubtraction_2x~dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bbiguduk/Swift_language_guide_kr/6d2a3ab844d345a6db5e37263bce1d8fa8547b4a/.gitbook/assets/overflowSignedSubtraction_2x~dark.png
--------------------------------------------------------------------------------
/.gitbook/assets/overflowUnsignedSubtraction_2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bbiguduk/Swift_language_guide_kr/6d2a3ab844d345a6db5e37263bce1d8fa8547b4a/.gitbook/assets/overflowUnsignedSubtraction_2x.png
--------------------------------------------------------------------------------
/.gitbook/assets/overflowUnsignedSubtraction_2x~dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bbiguduk/Swift_language_guide_kr/6d2a3ab844d345a6db5e37263bce1d8fa8547b4a/.gitbook/assets/overflowUnsignedSubtraction_2x~dark.png
--------------------------------------------------------------------------------
/.gitbook/assets/referenceCycle01_2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bbiguduk/Swift_language_guide_kr/6d2a3ab844d345a6db5e37263bce1d8fa8547b4a/.gitbook/assets/referenceCycle01_2x.png
--------------------------------------------------------------------------------
/.gitbook/assets/referenceCycle01_2x~dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bbiguduk/Swift_language_guide_kr/6d2a3ab844d345a6db5e37263bce1d8fa8547b4a/.gitbook/assets/referenceCycle01_2x~dark.png
--------------------------------------------------------------------------------
/.gitbook/assets/referenceCycle02_2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bbiguduk/Swift_language_guide_kr/6d2a3ab844d345a6db5e37263bce1d8fa8547b4a/.gitbook/assets/referenceCycle02_2x.png
--------------------------------------------------------------------------------
/.gitbook/assets/referenceCycle02_2x~dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bbiguduk/Swift_language_guide_kr/6d2a3ab844d345a6db5e37263bce1d8fa8547b4a/.gitbook/assets/referenceCycle02_2x~dark.png
--------------------------------------------------------------------------------
/.gitbook/assets/referenceCycle03_2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bbiguduk/Swift_language_guide_kr/6d2a3ab844d345a6db5e37263bce1d8fa8547b4a/.gitbook/assets/referenceCycle03_2x.png
--------------------------------------------------------------------------------
/.gitbook/assets/referenceCycle03_2x~dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bbiguduk/Swift_language_guide_kr/6d2a3ab844d345a6db5e37263bce1d8fa8547b4a/.gitbook/assets/referenceCycle03_2x~dark.png
--------------------------------------------------------------------------------
/.gitbook/assets/remainderInteger_2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bbiguduk/Swift_language_guide_kr/6d2a3ab844d345a6db5e37263bce1d8fa8547b4a/.gitbook/assets/remainderInteger_2x.png
--------------------------------------------------------------------------------
/.gitbook/assets/remainderInteger_2x~dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bbiguduk/Swift_language_guide_kr/6d2a3ab844d345a6db5e37263bce1d8fa8547b4a/.gitbook/assets/remainderInteger_2x~dark.png
--------------------------------------------------------------------------------
/.gitbook/assets/setEulerDiagram_2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bbiguduk/Swift_language_guide_kr/6d2a3ab844d345a6db5e37263bce1d8fa8547b4a/.gitbook/assets/setEulerDiagram_2x.png
--------------------------------------------------------------------------------
/.gitbook/assets/setEulerDiagram_2x~dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bbiguduk/Swift_language_guide_kr/6d2a3ab844d345a6db5e37263bce1d8fa8547b4a/.gitbook/assets/setEulerDiagram_2x~dark.png
--------------------------------------------------------------------------------
/.gitbook/assets/setVennDiagram_2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bbiguduk/Swift_language_guide_kr/6d2a3ab844d345a6db5e37263bce1d8fa8547b4a/.gitbook/assets/setVennDiagram_2x.png
--------------------------------------------------------------------------------
/.gitbook/assets/setVennDiagram_2x~dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bbiguduk/Swift_language_guide_kr/6d2a3ab844d345a6db5e37263bce1d8fa8547b4a/.gitbook/assets/setVennDiagram_2x~dark.png
--------------------------------------------------------------------------------
/.gitbook/assets/sharedStateClass_2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bbiguduk/Swift_language_guide_kr/6d2a3ab844d345a6db5e37263bce1d8fa8547b4a/.gitbook/assets/sharedStateClass_2x.png
--------------------------------------------------------------------------------
/.gitbook/assets/sharedStateClass_2x~dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bbiguduk/Swift_language_guide_kr/6d2a3ab844d345a6db5e37263bce1d8fa8547b4a/.gitbook/assets/sharedStateClass_2x~dark.png
--------------------------------------------------------------------------------
/.gitbook/assets/sharedStateStruct_2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bbiguduk/Swift_language_guide_kr/6d2a3ab844d345a6db5e37263bce1d8fa8547b4a/.gitbook/assets/sharedStateStruct_2x.png
--------------------------------------------------------------------------------
/.gitbook/assets/sharedStateStruct_2x~dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bbiguduk/Swift_language_guide_kr/6d2a3ab844d345a6db5e37263bce1d8fa8547b4a/.gitbook/assets/sharedStateStruct_2x~dark.png
--------------------------------------------------------------------------------
/.gitbook/assets/snakesAndLadders_2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bbiguduk/Swift_language_guide_kr/6d2a3ab844d345a6db5e37263bce1d8fa8547b4a/.gitbook/assets/snakesAndLadders_2x.png
--------------------------------------------------------------------------------
/.gitbook/assets/snakesAndLadders_2x~dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bbiguduk/Swift_language_guide_kr/6d2a3ab844d345a6db5e37263bce1d8fa8547b4a/.gitbook/assets/snakesAndLadders_2x~dark.png
--------------------------------------------------------------------------------
/.gitbook/assets/stackPoppedOneString_2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bbiguduk/Swift_language_guide_kr/6d2a3ab844d345a6db5e37263bce1d8fa8547b4a/.gitbook/assets/stackPoppedOneString_2x.png
--------------------------------------------------------------------------------
/.gitbook/assets/stackPoppedOneString_2x~dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bbiguduk/Swift_language_guide_kr/6d2a3ab844d345a6db5e37263bce1d8fa8547b4a/.gitbook/assets/stackPoppedOneString_2x~dark.png
--------------------------------------------------------------------------------
/.gitbook/assets/stackPushPop_2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bbiguduk/Swift_language_guide_kr/6d2a3ab844d345a6db5e37263bce1d8fa8547b4a/.gitbook/assets/stackPushPop_2x.png
--------------------------------------------------------------------------------
/.gitbook/assets/stackPushPop_2x~dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bbiguduk/Swift_language_guide_kr/6d2a3ab844d345a6db5e37263bce1d8fa8547b4a/.gitbook/assets/stackPushPop_2x~dark.png
--------------------------------------------------------------------------------
/.gitbook/assets/stackPushedFourStrings_2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bbiguduk/Swift_language_guide_kr/6d2a3ab844d345a6db5e37263bce1d8fa8547b4a/.gitbook/assets/stackPushedFourStrings_2x.png
--------------------------------------------------------------------------------
/.gitbook/assets/stackPushedFourStrings_2x~dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bbiguduk/Swift_language_guide_kr/6d2a3ab844d345a6db5e37263bce1d8fa8547b4a/.gitbook/assets/stackPushedFourStrings_2x~dark.png
--------------------------------------------------------------------------------
/.gitbook/assets/staticPropertiesVUMeter_2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bbiguduk/Swift_language_guide_kr/6d2a3ab844d345a6db5e37263bce1d8fa8547b4a/.gitbook/assets/staticPropertiesVUMeter_2x.png
--------------------------------------------------------------------------------
/.gitbook/assets/staticPropertiesVUMeter_2x~dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bbiguduk/Swift_language_guide_kr/6d2a3ab844d345a6db5e37263bce1d8fa8547b4a/.gitbook/assets/staticPropertiesVUMeter_2x~dark.png
--------------------------------------------------------------------------------
/.gitbook/assets/stringSubstring_2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bbiguduk/Swift_language_guide_kr/6d2a3ab844d345a6db5e37263bce1d8fa8547b4a/.gitbook/assets/stringSubstring_2x.png
--------------------------------------------------------------------------------
/.gitbook/assets/stringSubstring_2x~dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bbiguduk/Swift_language_guide_kr/6d2a3ab844d345a6db5e37263bce1d8fa8547b4a/.gitbook/assets/stringSubstring_2x~dark.png
--------------------------------------------------------------------------------
/.gitbook/assets/subscriptMatrix01_2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bbiguduk/Swift_language_guide_kr/6d2a3ab844d345a6db5e37263bce1d8fa8547b4a/.gitbook/assets/subscriptMatrix01_2x.png
--------------------------------------------------------------------------------
/.gitbook/assets/subscriptMatrix01_2x~dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bbiguduk/Swift_language_guide_kr/6d2a3ab844d345a6db5e37263bce1d8fa8547b4a/.gitbook/assets/subscriptMatrix01_2x~dark.png
--------------------------------------------------------------------------------
/.gitbook/assets/subscriptMatrix02_2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bbiguduk/Swift_language_guide_kr/6d2a3ab844d345a6db5e37263bce1d8fa8547b4a/.gitbook/assets/subscriptMatrix02_2x.png
--------------------------------------------------------------------------------
/.gitbook/assets/subscriptMatrix02_2x~dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bbiguduk/Swift_language_guide_kr/6d2a3ab844d345a6db5e37263bce1d8fa8547b4a/.gitbook/assets/subscriptMatrix02_2x~dark.png
--------------------------------------------------------------------------------
/.gitbook/assets/twoPhaseInitialization01_2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bbiguduk/Swift_language_guide_kr/6d2a3ab844d345a6db5e37263bce1d8fa8547b4a/.gitbook/assets/twoPhaseInitialization01_2x.png
--------------------------------------------------------------------------------
/.gitbook/assets/twoPhaseInitialization01_2x~dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bbiguduk/Swift_language_guide_kr/6d2a3ab844d345a6db5e37263bce1d8fa8547b4a/.gitbook/assets/twoPhaseInitialization01_2x~dark.png
--------------------------------------------------------------------------------
/.gitbook/assets/twoPhaseInitialization02_2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bbiguduk/Swift_language_guide_kr/6d2a3ab844d345a6db5e37263bce1d8fa8547b4a/.gitbook/assets/twoPhaseInitialization02_2x.png
--------------------------------------------------------------------------------
/.gitbook/assets/twoPhaseInitialization02_2x~dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bbiguduk/Swift_language_guide_kr/6d2a3ab844d345a6db5e37263bce1d8fa8547b4a/.gitbook/assets/twoPhaseInitialization02_2x~dark.png
--------------------------------------------------------------------------------
/.gitbook/assets/unownedOptionalReference_2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bbiguduk/Swift_language_guide_kr/6d2a3ab844d345a6db5e37263bce1d8fa8547b4a/.gitbook/assets/unownedOptionalReference_2x.png
--------------------------------------------------------------------------------
/.gitbook/assets/unownedOptionalReference_2x~dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bbiguduk/Swift_language_guide_kr/6d2a3ab844d345a6db5e37263bce1d8fa8547b4a/.gitbook/assets/unownedOptionalReference_2x~dark.png
--------------------------------------------------------------------------------
/.gitbook/assets/unownedReference01_2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bbiguduk/Swift_language_guide_kr/6d2a3ab844d345a6db5e37263bce1d8fa8547b4a/.gitbook/assets/unownedReference01_2x.png
--------------------------------------------------------------------------------
/.gitbook/assets/unownedReference01_2x~dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bbiguduk/Swift_language_guide_kr/6d2a3ab844d345a6db5e37263bce1d8fa8547b4a/.gitbook/assets/unownedReference01_2x~dark.png
--------------------------------------------------------------------------------
/.gitbook/assets/unownedReference02_2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bbiguduk/Swift_language_guide_kr/6d2a3ab844d345a6db5e37263bce1d8fa8547b4a/.gitbook/assets/unownedReference02_2x.png
--------------------------------------------------------------------------------
/.gitbook/assets/unownedReference02_2x~dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bbiguduk/Swift_language_guide_kr/6d2a3ab844d345a6db5e37263bce1d8fa8547b4a/.gitbook/assets/unownedReference02_2x~dark.png
--------------------------------------------------------------------------------
/.gitbook/assets/vectorAddition_2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bbiguduk/Swift_language_guide_kr/6d2a3ab844d345a6db5e37263bce1d8fa8547b4a/.gitbook/assets/vectorAddition_2x.png
--------------------------------------------------------------------------------
/.gitbook/assets/vectorAddition_2x~dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bbiguduk/Swift_language_guide_kr/6d2a3ab844d345a6db5e37263bce1d8fa8547b4a/.gitbook/assets/vectorAddition_2x~dark.png
--------------------------------------------------------------------------------
/.gitbook/assets/weakReference01_2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bbiguduk/Swift_language_guide_kr/6d2a3ab844d345a6db5e37263bce1d8fa8547b4a/.gitbook/assets/weakReference01_2x.png
--------------------------------------------------------------------------------
/.gitbook/assets/weakReference01_2x~dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bbiguduk/Swift_language_guide_kr/6d2a3ab844d345a6db5e37263bce1d8fa8547b4a/.gitbook/assets/weakReference01_2x~dark.png
--------------------------------------------------------------------------------
/.gitbook/assets/weakReference02_2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bbiguduk/Swift_language_guide_kr/6d2a3ab844d345a6db5e37263bce1d8fa8547b4a/.gitbook/assets/weakReference02_2x.png
--------------------------------------------------------------------------------
/.gitbook/assets/weakReference02_2x~dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bbiguduk/Swift_language_guide_kr/6d2a3ab844d345a6db5e37263bce1d8fa8547b4a/.gitbook/assets/weakReference02_2x~dark.png
--------------------------------------------------------------------------------
/.gitbook/assets/weakReference03_2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bbiguduk/Swift_language_guide_kr/6d2a3ab844d345a6db5e37263bce1d8fa8547b4a/.gitbook/assets/weakReference03_2x.png
--------------------------------------------------------------------------------
/.gitbook/assets/weakReference03_2x~dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bbiguduk/Swift_language_guide_kr/6d2a3ab844d345a6db5e37263bce1d8fa8547b4a/.gitbook/assets/weakReference03_2x~dark.png
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # The Swift Programming Language (6) (한국어)
2 |
3 | [](https://github.com/anuraghazra/github-readme-stats)
4 |
5 | ## The Swift Programming Language
6 |
7 | [https://docs.swift.org/swift-book/](https://docs.swift.org/swift-book/) 에 있는 [The Swift Programming Language](https://docs.swift.org/swift-book/) 을 한국어로 번역한 것이며, 오역 및 오타 많을 수 있습니다. 발견 시 연락처에 있는 email로 연락해 주세요!
8 |
9 | ### 온라인 문서
10 |
11 | [GitBook](https://bbiguduk.gitbook.io/swift)
12 |
13 | ### 업데이트
14 |
15 | * [Swift 6.1, 2025-04-02](revision-history/document-revision-history.md#2025-04-02수)
16 | * [Swift 6, 2024-09-19](revision-history/document-revision-history.md#2024-09-19목)
17 | * [Swift 5.10, 2024-03-08](revision-history/document-revision-history.md#2024-03-08금)
18 | * [Swift 5.9.2, 2023-12-12](revision-history/document-revision-history.md#2023-12-12)
19 | * [Swift 5.9, 2023-09-30](revision-history/document-revision-history.md#2023-09-30)
20 | * [Swift 5.8, 2023-04-04](revision-history/document-revision-history.md#2023-04-04)
21 | * [Swift 5.7, 2022-09-13](revision-history/document-revision-history.md#2022-09-13)
22 | * [Swift 5.6, 2022-03-17](revision-history/document-revision-history.md#2022-03-17)
23 | * [Swift 5.5, 2021-08-14](revision-history/document-revision-history.md#2021-08-14)
24 | * [Swift 5.4, 2021-02-20](revision-history/document-revision-history.md#2021-02-20)
25 | * [Swift 5.3, 2020-10-23](revision-history/document-revision-history.md#2020-10-23)
26 |
27 | ### 번역용어
28 |
29 | | 원문 | 번역문 |
30 | | ---------------------------- | ------------ |
31 | | String | 문자열 |
32 | | Array | 배열 |
33 | | Dictionary | 딕셔너리 |
34 | | Boolean | 부울 |
35 | | Optional | 옵셔널 |
36 | | Switch | 스위치 |
37 | | Integer | 정수 |
38 | | Case | 케이스 |
39 | | Collection | 콜렉션 |
40 | | Function | 함수 |
41 | | Return | 반환 |
42 | | Type | 타입 |
43 | | Parameter | 파라미터 |
44 | | Argument | 인수 |
45 | | Tuple | 튜플 |
46 | | Closure | 클로저 |
47 | | Delegate | 대리자 |
48 | | Class | 클래스 |
49 | | Context | 컨텍스트 |
50 | | Initializer | 초기화 구문 |
51 | | Deinitializer | 초기화 해제 구문 |
52 | | Subclass | 하위 클래스 |
53 | | Superclass | 상위 클래스 |
54 | | Property | 프로퍼티 |
55 | | Getter | Getter |
56 | | Setter | Setter |
57 | | Method | 메서드 |
58 | | Subscript | 서브 스크립트 |
59 | | Raw value | 원시값 |
60 | | Enumeration | 열거형 |
61 | | Structure | 구조체 |
62 | | Associated value | 연관된 값 |
63 | | Protocol | 프로토콜 |
64 | | Extension | 확장 |
65 | | Generic | 제너릭 |
66 | | Type-safe | 타입-세이프 |
67 | | Annotation | 명시 |
68 | | Inference | 추론 |
69 | | Backtick | 백틱 |
70 | | Comment | 주석 |
71 | | Asterisk | 애스터리스크 |
72 | | Literal | 리터럴 |
73 | | Alias | 별칭 |
74 | | Optional Binding | 옵셔널 바인딩 |
75 | | Assertion | 역설 |
76 | | Precondition | 전제조건 |
77 | | Operator | 연산자 |
78 | | Overflow | 오버플로우 |
79 | | Terminology | 술어 |
80 | | Unary | 단항 |
81 | | Binary | 이항 |
82 | | Ternary | 삼항 |
83 | | Value Type | 값 타입 |
84 | | Unicode | 유니코드 |
85 | | Substring | 부분 문자열 |
86 | | Set | 집합 |
87 | | mutable | 변경 가능 |
88 | | Control | 제어 |
89 | | Statement | 구문 |
90 | | Implicit | 암시적 |
91 | | Nested | 중첩 |
92 | | Closing Over | 폐쇄 |
93 | | Trailing Closure | 후행 클로저 |
94 | | Escaping Closure | 탈출 클로저 |
95 | | Autoclosure | 자동 클로저 |
96 | | Actor | 액터 |
97 | | Reference Type | 참조 타입 |
98 | | Instance Property | 인스턴스 프로퍼티 |
99 | | Stored Property | 저장된 프로퍼티 |
100 | | Computed Property | 계산된 프로퍼티 |
101 | | Property Observer | 프로퍼티 관찰자 |
102 | | Property Wrapper | 프로퍼티 래퍼 |
103 | | Projected Value | 투영된 값 |
104 | | Type Property | 타입 프로퍼티 |
105 | | Instance Method | 인스턴스 메서드 |
106 | | Type Method | 타입 메서드 |
107 | | List | 리스트 |
108 | | Type Subscript | 타입 서브 스크립트 |
109 | | Inheritance | 상속 |
110 | | Overriding | 재정의 |
111 | | Delegation | 위임 |
112 | | Designated Initializer | 지정된 초기화 구문 |
113 | | Convenience Initializer | 편의 초기화 구문 |
114 | | Optional Chaining | 옵셔널 체이닝 |
115 | | Error Handling | 에러 처리 |
116 | | Concurrency | 동시성 |
117 | | Asynchronous | 비동기 |
118 | | Parallel | 병렬 |
119 | | Structed Concurrency | 구조화된 동시성 |
120 | | Unstructed Concurrency | 구조화되지 않은 동시성 |
121 | | Type Parameter | 타입 파라미터 |
122 | | Opaque Type | 불투명한 타입 |
123 | | Automatic Reference Counting | 자동 참조 카운팅 |
124 | | Strong Reference Cycle | 강한 참조 사이클 |
125 | | Weak Reference | 약한 참조 |
126 | | Unowned Reference | 미소유 참조 |
127 | | Capture List | 캡처 리스트 |
128 | | Access Control | 접근 제어 |
129 | | Access Level | 접근 수준 |
130 | | Bitwise Operator | 비트 연산자 |
131 | | Result Builder | 결과 빌더 |
132 |
133 | ### 차례
134 |
135 | | 속성 | 위치 |
136 | | --------- | -------------------------------------------------------------------------------- |
137 | | 기본 | [The Basic](language-guide-1/the-basics.md) |
138 | | 기본 연산자 | [Basic Operators](language-guide-1/basic-operators.md) |
139 | | 문자열과 문자 | [Strings and Characters](language-guide-1/strings-and-characters.md) |
140 | | 콜렉션 타입 | [Collection Types](language-guide-1/collection-types.md) |
141 | | 제어 흐름 | [Control Flow](language-guide-1/control-flow.md) |
142 | | 함수 | [Functions](language-guide-1/functions.md) |
143 | | 클로저 | [Closures](language-guide-1/closures.md) |
144 | | 열거형 | [Enumerations](language-guide-1/enumerations.md) |
145 | | 구조체와 클래스 | [Structures and Classes](language-guide-1/structures-and-classes.md) |
146 | | 프로퍼티 | [Properties](language-guide-1/properties.md) |
147 | | 메서드 | [Methods](language-guide-1/methods.md) |
148 | | 서브 스크립트 | [Subscripts](language-guide-1/subscripts.md) |
149 | | 상속 | [Inheritance](language-guide-1/inheritance.md) |
150 | | 초기화 | [Initialization](language-guide-1/initialization.md) |
151 | | 초기화 해제 | [Deinitialization](language-guide-1/deinitialization.md) |
152 | | 옵셔널 체이닝 | [Optional Chaining](language-guide-1/optional-chaining.md) |
153 | | 에러 처리 | [Error Handling](language-guide-1/error-handling.md) |
154 | | 동시성 | [Concurrency](language-guide-1/concurrency.md) |
155 | | 타입 캐스팅 | [Type Casting](language-guide-1/type-casting.md) |
156 | | 중첩된 타입 | [Nested Types](language-guide-1/nested-types.md) |
157 | | 확장 | [Extensions](language-guide-1/extensions.md) |
158 | | 프로토콜 | [Protocols](language-guide-1/protocols.md) |
159 | | 제너릭 | [Generics](language-guide-1/generics.md) |
160 | | 불투명한 타입 | [Opaque Types](language-guide-1/opaque-types.md) |
161 | | 자동 참조 카운팅 | [Automatic Reference Counting](language-guide-1/automatic-reference-counting.md) |
162 | | 메모리 안전성 | [Memory Safety](language-guide-1/memory-safety.md) |
163 | | 접근 제어 | [Access Control](language-guide-1/access-control.md) |
164 | | 고급 연산자 | [Advanced Operators](language-guide-1/advanced-operators.md) |
165 |
--------------------------------------------------------------------------------
/SUMMARY.md:
--------------------------------------------------------------------------------
1 | # Table of contents
2 |
3 | * [The Swift Programming Language (한국어)](README.md)
4 |
5 | ## WELCOME TO SWIFT
6 |
7 | * [Swift 에 대해 (About Swift)](welcome-to-swift/swift-about-swift.md)
8 | * [버전 호환성 (Version Compatibility)](welcome-to-swift/version-compatibility.md)
9 | * [Swift 둘러보기 (A Swift Tour)](welcome-to-swift/swift-a-swift-tour.md)
10 |
11 | ## Language Guide
12 |
13 | * [기본 (The Basics)](language-guide-1/the-basics.md)
14 | * [기본 연산자 (Basic Operators)](language-guide-1/basic-operators.md)
15 | * [문자열과 문자 (Strings and Characters)](language-guide-1/strings-and-characters.md)
16 | * [콜렉션 타입 (Collection Types)](language-guide-1/collection-types.md)
17 | * [제어 흐름 (Control Flow)](language-guide-1/control-flow.md)
18 | * [함수 (Functions)](language-guide-1/functions.md)
19 | * [클로저 (Closures)](language-guide-1/closures.md)
20 | * [열거형 (Enumerations)](language-guide-1/enumerations.md)
21 | * [구조체와 클래스 (Structures and Classes)](language-guide-1/structures-and-classes.md)
22 | * [프로퍼티 (Properties)](language-guide-1/properties.md)
23 | * [메서드 (Methods)](language-guide-1/methods.md)
24 | * [서브 스크립트 (Subscripts)](language-guide-1/subscripts.md)
25 | * [상속 (Inheritance)](language-guide-1/inheritance.md)
26 | * [초기화 (Initialization)](language-guide-1/initialization.md)
27 | * [초기화 해제 (Deinitialization)](language-guide-1/deinitialization.md)
28 | * [옵셔널 체이닝 (Optional Chaining)](language-guide-1/optional-chaining.md)
29 | * [에러 처리 (Error Handling)](language-guide-1/error-handling.md)
30 | * [동시성 (Concurrency)](language-guide-1/concurrency.md)
31 | * [매크로 (Macros)](language-guide-1/macros.md)
32 | * [타입 캐스팅 (Type Casting)](language-guide-1/type-casting.md)
33 | * [중첩된 타입 (Nested Types)](language-guide-1/nested-types.md)
34 | * [확장 (Extensions)](language-guide-1/extensions.md)
35 | * [프로토콜 (Protocols)](language-guide-1/protocols.md)
36 | * [제너릭 (Generics)](language-guide-1/generics.md)
37 | * [불투명한 타입 (Opaque Types)](language-guide-1/opaque-types.md)
38 | * [자동 참조 카운팅 (Automatic Reference Counting)](language-guide-1/automatic-reference-counting.md)
39 | * [메모리 안전성 (Memory Safety)](language-guide-1/memory-safety.md)
40 | * [접근 제어 (Access Control)](language-guide-1/access-control.md)
41 | * [고급 연산자 (Advanced Operators)](language-guide-1/advanced-operators.md)
42 |
43 | ## LANGUAGE REFERENCE
44 |
45 | * [언어 참조에 대해 (About the Language Reference)](language-reference/about-the-language-reference.md)
46 | * [어휘 구조 (Lexical Structure)](language-reference/lexical-structure.md)
47 | * [타입 (Types)](language-reference/types.md)
48 | * [표현식 (Expressions)](language-reference/expressions.md)
49 | * [구문 (Statements)](language-reference/statements.md)
50 | * [선언 (Declarations)](language-reference/declarations.md)
51 | * [속성 (Attributes)](language-reference/attributes.md)
52 | * [패턴 (Patterns)](language-reference/patterns.md)
53 | * [제너릭 파라미터와 인수 (Generic Parameters and Arguments)](language-reference/generic-parameters-and-arguments.md)
54 | * [문법 정리 (Summary of the Grammar)](language-reference/summary-of-the-grammar.md)
55 |
56 | ## Contact
57 |
58 | * [연락처](contact/undefined.md)
59 |
60 | ## Revision History
61 |
62 | * [Document Revision History](revision-history/document-revision-history.md)
63 |
--------------------------------------------------------------------------------
/contact/undefined.md:
--------------------------------------------------------------------------------
1 | ---
2 | description: 오역이나 오타 발견 시 아래 연락처로 연락 바랍니다.
3 | ---
4 |
5 | # 연락처
6 |
7 | ### Contact Point
8 |
9 | * Email: bbiguduk@gmail.com
10 |
11 |
--------------------------------------------------------------------------------
/language-guide-1/deinitialization.md:
--------------------------------------------------------------------------------
1 | # 초기화 해제 \(Deinitialization\)
2 |
3 | 정리가 필요한 리소스를 해제합니다.
4 |
5 | _초기화 해제 구문 \(deinitializer\)_ 는 클래스 인스턴스가 할당 해제되기 직전에 호출됩니다. 초기화 구문은 `init` 키워드로 작성하는 것과 유사하게 초기화 해제는 `deinit` 키워드로 작성합니다. 초기화 해제는 클래스 타입에서만 사용 가능합니다.
6 |
7 | ## 초기화 해제 동작 \(How Deinitialization Works\)
8 |
9 | Swift는 더이상 필요하지 않을 때 자원 확보를 위해 인스턴스를 자동으로 할당 해제합니다. Swift는 [자동 참조 카운팅 \(Automatic Reference Counting\)](automatic-reference-counting.md) 에서 설명되어 있듯이 _자동 참조 카운팅 \(ARC\)_ 를 통해 인스턴스의 메모리를 관리합니다. 일반적으로 인스턴스가 할당 해제될 때 수동으로 수행할 필요는 없습니다. 그러나 자체 자원으로 작업하는 경우 추가 정리로 직접 수행이 필요한 경우가 있습니다. 예를 들어 파일을 열고 데이터를 작성하는 클래스를 생성하면 클래스 인스턴스를 할당 해제하기 전에 파일을 닫아야 합니다.
10 |
11 | 클래스 초기화 해제는 클래스 당 하나의 초기화 해제 구문만 가지고 있습니다. 이 초기화 해제 구문은 파라미터가 없고 소괄호 없이 작성됩니다:
12 |
13 | ```swift
14 | deinit {
15 | // perform the deinitialization
16 | }
17 | ```
18 |
19 | 초기화 해제 구문은 인스턴스가 할당 해제 되기 직전에 자동으로 호출됩니다. 초기화 해제 구문을 직접 호출할 수는 없습니다. 상위 클래스 초기화 해제 구문은 하위 클래스로 상속되고 상위 클래스 초기화 해제 구문은 하위 클래스 초기화 해제 구문 구현이 끝날 때 자동으로 호출됩니다. 상위 클래스 초기화 해제 구문은 하위 클래스가 자신의 초기화 해제 구문을 제공하지 않더라도 항상 호출됩니다.
20 |
21 | 인스턴스는 초기화 해제 구문이 호출되기 전에는 할당 해제되지 않기 때문에 예를 들어 닫아야 하는 파일의 이름에 접근하듯 초기화 해제 구문은 인스턴스의 모든 프로퍼티에 접근할 수 있고 프로퍼티 기반으로 동작을 수정할 수 있습니다.
22 |
23 | ## 초기화 해제 구문 동작 \(Deinitializers in Action\)
24 |
25 | 다음은 초기화 해제 구문에 대한 동작의 예입니다. 이 예제는 간단한 게임을 위해 `Bank` 와 `Player` 라는 2개의 새로운 타입을 정의합니다. `Bank` 클래스는 유통중인 코인이 10,000개를 넘을 수 없는 구성 통화를 관리합니다. 게임에서는 하나의 `Bank` 만 가질 수 있으므로 `Bank` 는 현재 상태를 저장하고 관리하기 위해 타입 프로퍼티와 타입 메서드를 가진 클래스로 구현됩니다:
26 |
27 | ```swift
28 | class Bank {
29 | static var coinsInBank = 10_000
30 | static func distribute(coins numberOfCoinsRequested: Int) -> Int {
31 | let numberOfCoinsToVend = min(numberOfCoinsRequested, coinsInBank)
32 | coinsInBank -= numberOfCoinsToVend
33 | return numberOfCoinsToVend
34 | }
35 | static func receive(coins: Int) {
36 | coinsInBank += coins
37 | }
38 | }
39 | ```
40 |
41 | `Bank` 는 `coinsInBank` 프로퍼티를 통해 현재 코인의 갯수를 추적합니다. 또한 코인의 분배와 수집을 처리하기 위해 `distribute(coins:)` 와 `receive(coins:)` 인 2개의 메서드를 제공합니다.
42 |
43 | `distribute(coins:)` 메서드는 코인을 분배하기 전에 은행에 코인이 충분한지 검사합니다. 코인이 충분하지 않으면 `Bank` 는 요청된 수보다 더 작은 수를 반환하고 코인이 은행에 남아있지 않은 경우 0을 반환합니다. 제공된 실제 코인 수를 나타내는 정수를 반환합니다.
44 |
45 | `receive(coins:)` 메서드는 받은 코인의 수를 은행의 코인 저장소에 추가합니다.
46 |
47 | `Player` 클래스는 게임에 플레이어를 설명합니다. 각 플레이어는 언제든지 지갑에 특정 수의 동전을 보관합니다. 이것은 플레이어의 `coinsInPurse` 프로퍼티에 표시됩니다:
48 |
49 | ```swift
50 | class Player {
51 | var coinsInPurse: Int
52 | init(coins: Int) {
53 | coinsInPurse = Bank.distribute(coins: coins)
54 | }
55 | func win(coins: Int) {
56 | coinsInPurse += Bank.distribute(coins: coins)
57 | }
58 | deinit {
59 | Bank.receive(coins: coinsInPurse)
60 | }
61 | }
62 | ```
63 |
64 | 각 `Player` 인스턴스는 초기화 하는 동안 은행에서 지정된 수의 코인을 시작 허용량으로 초기화 되지만 사용할 수 있는 코인이 충분하지 않은 경우 `Player` 인스턴스는 해당 수보다 적게 받을 수 있습니다.
65 |
66 | `Player` 클래스는 은행에서 특정 수의 코인을 가져오고 플레이어의 지갑에 더하는 `win(coins:)` 메서드를 정의합니다. `Player` 클래스는 `Player` 인스턴스가 할당 해제되기 전에 호출되는 초기화 해제 구문도 구현합니다. 여기서 초기화 해제 구문은 단순하게 플레이어의 모든 코인을 은행에 반환합니다:
67 |
68 | ```swift
69 | var playerOne: Player? = Player(coins: 100)
70 | print("A new player has joined the game with \(playerOne!.coinsInPurse) coins")
71 | // Prints "A new player has joined the game with 100 coins"
72 | print("There are now \(Bank.coinsInBank) coins left in the bank")
73 | // Prints "There are now 9900 coins left in the bank"
74 | ```
75 |
76 | 새로운 `Player` 인스턴스는 가능하면 100개의 코인을 요청하여 생성됩니다. `Player` 인스턴스는 `playerOne` 이라는 옵셔널 `Player` 변수에 저장됩니다. 플레이어는 언제나 게임을 떠날 수 있기 때문에 옵셔널 변수가 사용됩니다. 이 옵셔널은 현재 게임에서 플레이어 인지 확인합니다.
77 |
78 | `playerOne` 은 옵셔널 이기 때문에 기본 코인의 수를 출력하기 위해 `coinsInPurse` 프로퍼티에 접근할 때와 `win(coins:)` 메서드가 호출 될 때마다 느낌표 \(`!`\)를 붙입니다:
79 |
80 | ```swift
81 | playerOne!.win(coins: 2_000)
82 | print("PlayerOne won 2000 coins & now has \(playerOne!.coinsInPurse) coins")
83 | // Prints "PlayerOne won 2000 coins & now has 2100 coins"
84 | print("The bank now only has \(Bank.coinsInBank) coins left")
85 | // Prints "The bank now only has 7900 coins left"
86 | ```
87 |
88 | 여기서 플레이어는 2,000 코인을 가지고 있습니다. 플레이어의 지갑은 2,100 코인이 있고 은행은 7,900 코인이 남아 있습니다.
89 |
90 | ```swift
91 | playerOne = nil
92 | print("PlayerOne has left the game")
93 | // Prints "PlayerOne has left the game"
94 | print("The bank now has \(Bank.coinsInBank) coins")
95 | // Prints "The bank now has 10000 coins"
96 | ```
97 |
98 | 플레이어는 지금 게임을 떠납니다. 이것을 나타내기 위해 `playerOne` 옵셔널 변수에 "`Player` 인스턴스 없음"을 나타내는 `nil` 을 설정합니다. 이 시점에 `Player` 인스턴스에 대한 `playerOne` 변수의 참조가 끊어집니다. 다른 프로퍼티 또는 변수는 여전히 `Player` 인스턴스를 참조하고 있으므로 메모리 확보를 위해 할당 해제 됩니다. 이것이 일어나기 직전에 자동으로 초기화 해제 구문이 호출되고 코인은 은행에 반환됩니다.
99 |
100 |
--------------------------------------------------------------------------------
/language-guide-1/enumerations.md:
--------------------------------------------------------------------------------
1 | # 열거형 \(Enumerations\)
2 |
3 | 리스트의 가능한 값으로 정의한 사용자 정의 타입을 모델링합니다.
4 |
5 | _열거형 \(enumeration\)_ 은 관련된 값의 그룹을 위한 일반 타입을 정의하고 코드에서 타입-세이프 방법으로 값을 동작하게 합니다.
6 |
7 | C에 익숙하다면 C 열거형은 정수값을 설정하기 위해 연관된 이름을 할당하는 것을 알고 있습니다. Swift에서의 열거형은 훨씬 유연하고 열거형의 각 케이스에 값을 제공하지 않아도 됩니다. 값 \(원시값\)이 각 열거형 케이스로 제공된다면 그 값은 문자열, 문자 또는 정수 또는 부동 소수 타입일 수 있습니다.
8 |
9 | 또는 열거형 케이스는 각 다른 케이스 값으로 저장될 모든 타입의 관련된 값을 지정할 수 있습니다. 하나의 열거형의 일부로 관련된 케이스의 공통 세트를 정의할 수 있으며 각각은 연관된 적절한 타입의 다른값 세트를 가지고 있습니다.
10 |
11 | Swift의 열거형은 그 자체로 1급 타입입니다. 열거형의 현재값에 대한 추가 정보를 제공하는 계산된 프로퍼티와 열거형이 나타내는 값과 관련된 기능을 제공하는 인스턴스 메서드와 같이 전통적으로 클래스에서만 지원되는 많은 기능을 채택합니다. 열거형은 케이스 초기값을 제공하기 위해 초기화를 정의할 수도 있습니다. 열거형은 기존 구현을 넘어 기능적으로 확장될 수도 있고 표준 기능을 제공하기 위해 프로토콜을 준수할 수 있습니다.
12 |
13 | 이러한 기능의 자세한 내용은 [프로퍼티 \(Properties\)](properties.md), [메서드 \(Methods\)](methods.md), [초기화 \(Initialization\)](initialization.md), [확장 \(Extensions\)](extensions.md), 과 [프로토콜 \(Protocols\)](protocols.md) 을 참고 바랍니다.
14 |
15 | ## 열거형 구문 \(Enumeration Syntax\)
16 |
17 | 열거형은 `enum` 키워드와 중괄호 안에 모든 정의를 위치시켜 나타냅니다:
18 |
19 | ```swift
20 | enum SomeEnumeration {
21 | // enumeration definition goes here
22 | }
23 | ```
24 |
25 | 다음 예제는 나침반의 4개의 주요 포인트를 나타냅니다:
26 |
27 | ```swift
28 | enum CompassPoint {
29 | case north
30 | case south
31 | case east
32 | case west
33 | }
34 | ```
35 |
36 | 열거형 안에 정의된 값 \(`north`, `south`, `east`, `west`\)은 _열거형 케이스 \(enumeration cases\)_ 입니다. 새로운 열거형 케이스를 나타내기 위해 `case` 키워드를 사용합니다.
37 |
38 | > Note
39 | > Swift 열거형 케이스는 C와 Objective-C 처럼 기본적으로 정수값을 설정하지 않습니다. 위 예제 `CompassPoint` 에 `north`, `south`, `east`, `west` 는 `0`, `1`, `2`, `3` 과 같지 않습니다. 대신 다른 열거형 케이스는 `CompassPoint` 의 명시적으로 정의된 타입으로 자체 값입니다.
40 |
41 | 여러개의 케이스는 콤마로 구분하여 한줄로 표기할 수 있습니다:
42 |
43 | ```swift
44 | enum Planet {
45 | case mercury, venus, earth, mars, jupiter, saturn, uranus, neptune
46 | }
47 | ```
48 |
49 | 각 열거형 정의는 새로운 타입으로 정의합니다. Swift의 다른 타입처럼 대문자로 시작하는 그들의 이름 \(`CompassPoint` 와 `Planet`\)이 타입입니다. 열거형 타입에 복수 이름이 아닌 단수 이름으로 지정하여 읽기 쉽습니다:
50 |
51 | ```swift
52 | var directionToHead = CompassPoint.west
53 | ```
54 |
55 | `directionToHead` 타입은 `CompassPoint` 의 가능한 값중 하나로 초기화 될 때 유추됩니다. `directionToHead` 는 `CompassPoint` 로 선언되고 더 짧게 점 구문을 사용하여 다른 `CompassPoint` 값을 설정할 수 있습니다:
56 |
57 | ```swift
58 | directionToHead = .east
59 | ```
60 |
61 | `directionToHead` 의 타입은 이미 알고 있으므로 값을 설정할 때 타입을 삭제할 수 있습니다. 따라서 명시적으로 타입화 된 열거형 값으로 작업할 때 코드를 쉽게 읽을 수 있습니다.
62 |
63 | ## 스위치 구문에서 열거형 값 일치 \(Matching Enumeration Values with Switch Statement\)
64 |
65 | `switch` 구문으로 각각의 열거형 값을 일치시킬 수 있습니다:
66 |
67 | ```swift
68 | directionToHead = .south
69 | switch directionToHead {
70 | case .north:
71 | print("Lots of planets have a north")
72 | case .south:
73 | print("Watch out for penguins")
74 | case .east:
75 | print("Where the sun rises")
76 | case .west:
77 | print("Where the skies are blue")
78 | }
79 | // Prints "Watch out for penguins"
80 | ```
81 |
82 | 이 코드를 아래와 같이 읽을 수 있습니다:
83 |
84 | "`directionToHead` 값을 고려합니다. `.north` 와 같은 케이스일 경우 `"Lots of planets have a north"` 를 출력합니다. `.south` 와 같은 케이스일 경우 `"Watch out for penguins"` 를 출력합니다."
85 |
86 | 등등
87 |
88 | [제어 흐름 \(Control Flow\)](control-flow.md) 에서 설명 했듯이 `switch` 구문은 열거형 케이스를 고려할 때 완벽해야 합니다. `.west` 에 대한 `case` 가 생략된다면 `CompassPoint` 케이스에 대해 모든 리스트이 고려되지 않았으므로 이 코드는 컴파일 되지 않습니다. 완전성을 요구하면 열거형 케이스가 실수로 생략되지 않도록 합니다.
89 |
90 | 모든 열거형 케이스에 대해 `case` 를 제공하는 것이 적절하지 않은 경우 명시적으로 해결되지 않은 사례를 포함하는 `default` 케이스를 제공할 수 있습니다:
91 |
92 | ```swift
93 | let somePlanet = Planet.earth
94 | switch somePlanet {
95 | case .earth:
96 | print("Mostly harmless")
97 | default:
98 | print("Not a safe place for humans")
99 | }
100 | // Prints "Mostly harmless"
101 | ```
102 |
103 | ## 열거형 케이스 반복 \(Iterating over Enumeration Cases\)
104 |
105 | 일부 열거형의 경우 열거형의 모든 케이스를 수집하는 것이 유용합니다. 열거형 이름 뒤에 `: CaseIterable` 을 작성하여 활성화 합니다. Swift는 열거형 타입에 `allCases` 프로퍼티로 모든 케이스를 수집하고 방출합니다. 다음은 예제입니다:
106 |
107 | ```swift
108 | enum Beverage: CaseIterable {
109 | case coffee, tea, juice
110 | }
111 | let numberOfChoices = Beverage.allCases.count
112 | print("\(numberOfChoices) beverages available")
113 | // Prints "3 beverages available"
114 | ```
115 |
116 | 위의 예제에서 `Beverage` 열거형에 모든 케이스를 포함하는 콜렉션에 접근하기 위해 `Beverage.allCases` 를 작성합니다. 다른 콜렉션 처럼 `allCases` 를 사용할 수 있습니다. 콜렉션의 요소는 열거형 타입의 인스턴스 이기 때문에 이 경우에는 `Beverage` 값들입니다. 위의 예제는 얼마나 많은 케이스가 존재하는지 계산하고 아래의 예제는 `for`-`in` 루프를 사용하여 모든 케이스를 반복합니다.
117 |
118 | ```swift
119 | for beverage in Beverage.allCases {
120 | print(beverage)
121 | }
122 | // coffee
123 | // tea
124 | // juice
125 | ```
126 |
127 | 위 예제에서 사용된 구문은 열거형이 [`CaseIterable`](https://developer.apple.com/documentation/swift/caseiterable) 프로토콜을 준수하는 것으로 표시합니다. 자세한 내용은 [프로토콜 \(Protocols\)](protocols.md) 을 참조 바랍니다.
128 |
129 | ## 연관된 값 \(Associated Values\)
130 |
131 | 이전 섹션에서 예제는 열거형 케이스가 어떻게 정의되고 값이 입력되는지 보여줍니다. 상수 또는 변수를 `Planet.earth` 로 설정하고 나중에 값을 체크할 수 있습니다. 그러나 경우에 따라 이러한 케이스 값과 함께 다른 타입의 값을 저장할 수 있는 것이 유용합니다. 이 추가적인 정보를 _연관된 값 \(associated value\)_ 라고 하며 해당 케이스를 코드에서 값으로 사용할 때마다 달라집니다.
132 |
133 | 주어진 타입의 연관된 값을 저장하기 위해 Swift 열거형을 정의할 수 있고 이 값 타입은 필요에 따라 열거형의 각 케이스에 따라 달라질 수 있습니다. 이와 유사한 열거형은 다른 프로그래밍 언어에서 _식별된 집합체 \(discriminated unions\)_, _태그된 집합체 \(tagged unions\)_ 또는 _변형 가능한 집합체 \(variants\)_ 로 알려져 있습니다.
134 |
135 | 예를 들어 재고 추적 시스템이 2가지 타입의 바코드로 제품을 추적해야 된다고 가정해 보겠습니다. 어떤 제품은 숫자 `0` 에서 `9` 를 사용하는 UPC 형식의 1D 바코드 라벨이 부착되어 있습니다. 각 바코드에는 숫자 시스템과 이어서 5자리의 제조업체 코드와 5자리의 제품 코드가 있습니다. 다음에는 코드가 올바르게 스캔되었는지 확인하기 위해 검사 숫자가 있습니다:
136 |
137 | 
138 |
139 | 다른 제품은 어떠한 ISO 8859-1 문자도 사용할 수 있고 2,953개의 문자까지 인코딩할 수 있는 QR 코드 형식의 2D 바코드 라벨이 부착되어 있습니다:
140 |
141 | 
142 |
143 | 재고 추적 시스템은 UPC 바코드를 4개의 정수로 된 튜플로 저장하고 QR 코드 바코드를 모든 길이의 문자열로 저장하는 것이 편리합니다.
144 |
145 | Swift에서 두 타입의 바코드를 정의하는 열거형은 다음과 같습니다:
146 |
147 | ```swift
148 | enum Barcode {
149 | case upc(Int, Int, Int, Int)
150 | case qrCode(String)
151 | }
152 | ```
153 |
154 | 이것은 아래와 같이 읽을 수 있습니다:
155 |
156 | "\(`Int, Int, Int, Int`\) 타입의 연관된 값을 가진 `upc` 또는 `String` 타입의 연관된 값을 가진 `qrCode` 를 취할 수 있는 `Barcode` 라는 열거형 타입을 정의합니다."
157 |
158 | 이 정의는 어떠한 실질적인 `Int` 또는 `String` 값을 제공하지 않습니다. 이것은 단지 `Barcode.upc` 또는 `Barcode.qrCode` 와 같을 때 `Barcode` 상수와 변수에 저장할 수 있는 연관된 값의 _타입_ 을 정의할 뿐입니다.
159 |
160 | 그러면 이러한 타입을 이용하여 새로운 바코드를 생성할 수 있습니다:
161 |
162 | ```swift
163 | var productBarcode = Barcode.upc(8, 85909, 51226, 3)
164 | ```
165 |
166 | 이 예제는 `productBarcode` 라 불리는 새로운 변수를 생성하고 연관된 튜플값인 `(8, 85909, 51226, 3)` 을 `Barcode.upc` 의 값으로 할당합니다.
167 |
168 | 같은 상품의 다른 바코드 타입을 할당할 수 있습니다:
169 |
170 | ```swift
171 | productBarcode = .qrCode("ABCDEFGHIJKLMNOP")
172 | ```
173 |
174 | 여기서 기존의 `Barcode.upc` 와 그것의 정수 값은 새로운 `Barcode.qrCode` 와 그것의 문자열 값으로 대체됩니다. `Barcode` 타입의 상수와 변수는 `.upc` 또는 `.qrCode` 모두 이것들과 연관된 값으로 저장할 수 있지만 오직 하나의 값만 저장할 수 있습니다.
175 |
176 | [스위치 구문으로 열거형 값 일치 \(Matching Enumeration Values with a Switch Statement\)](enumerations.md#switch-matching-enumeration-values-with-switch-statement) 에서의 예제와 유사하게 스위치 구문을 이용하여 다른 바코드 타입을 확인할 수 있습니다. 그러나 이번에는 관련값이 스위치 구문의 일부로 추출됩니다. `switch` 케이스의 본문 내에서 사용하기 위해 상수 \(`let` 접두사\) 또는 변수 \(`var` 접두사\)로 각 연관된 값을 추출합니다:
177 |
178 | ```swift
179 | switch productBarcode {
180 | case .upc(let numberSystem, let manufacturer, let product, let check):
181 | print("UPC: \(numberSystem), \(manufacturer), \(product), \(check).")
182 | case .qrCode(let productCode):
183 | print("QR code: \(productCode).")
184 | }
185 | // Prints "QR code: ABCDEFGHIJKLMNOP."
186 | ```
187 |
188 | 열거형 케이스를 위한 연관된 값 모두 상수로 추출하거나 변수로 추출하려면 간결하게 케이스 이름 앞에 `let` 또는 `var` 을 선언하면 됩니다:
189 |
190 | ```swift
191 | switch productBarcode {
192 | case let .upc(numberSystem, manufacturer, product, check):
193 | print("UPC : \(numberSystem), \(manufacturer), \(product), \(check).")
194 | case let .qrCode(productCode):
195 | print("QR code: \(productCode).")
196 | }
197 | // Prints "QR code: ABCDEFGHIJKLMNOP."
198 | ```
199 |
200 | ## 원시값 \(Raw Values\)
201 |
202 | [연관된 값 \(Associated Values\)](enumerations.md#associated-values) 에서의 바코드 예제는 어떻게 열거형 케이스에 다른 타입의 연관된 값을 저장한다고 선언 하는지를 보여줍니다. 연관된 값의 대안으로 열거형 케이스는 모두 동일한 타입의 기본값 \(_원시값 \(raw values\)_\)으로 미리 채워질 수 있습니다.
203 |
204 | 다음은 명명된 열거형 케이스와 함께 원시 ASCII 값을 저장하는 예입니다:
205 |
206 | ```swift
207 | enum ASCIIControlCharacter: Character {
208 | case tab = "\t"
209 | case lineFeed = "\n"
210 | case carriageReturn = "\r"
211 | }
212 | ```
213 |
214 | 여기서 `ASCIIControlCharacter` 라 하는 열거형의 원시값은 `Character` 타입으로 정의되고 일반적인 ASCII 제어 문자 중 일부를 선정합니다. `Character` 값은 [문자열과 문자 \(Strings and Characters\)](strings-and-characters.md) 에서 설명되어 있습니다.
215 |
216 | 원시값은 문자열, 문자, 또는 어떠한 정수 또는 부동소수점 숫자 타입이 가능합니다. 각 원시값은 열거형 선언부 내에서 유일한 값이어야 합니다.
217 |
218 | > Note
219 | > 원시값은 연관된 값 \(associated values\)과 같지 않습니다. 원시값은 위의 3개의 ASCII 코드처럼 코드에서 열거형을 처음 정의할 때 미리 설정하는 값입니다. 특정 열거형 케이스를 위한 원시값은 항상 같습니다. 연관된 값은 열거형 케이스 중 하나를 기반으로 새로운 상수 또는 변수를 생성할 때 설정하고 달라질 수 있습니다.
220 |
221 | ### 암시적으로 할당된 원시값 \(Implicitly Assigned Raw Values\)
222 |
223 | 정수 또는 문자열 원시값이 저장된 열거형으로 동작 시 각 케이스에 명시적으로 원시값을 가질 필요가 없습니다. 원시값을 설정하지 않으면 Swift는 자동적으로 값을 할당합니다.
224 |
225 | 예를 들어 정수를 원시값으로 사용하면 각 케이스의 암시적 값은 이전 케이스보다 하나씩 증가시킵니다. 첫번째 케이스에 값 설정이 안되어 있으면 `0` 으로 설정합니다.
226 |
227 | 아래의 열거형은 태양으로 부터 각 행성의 순서를 정수값으로 나타내는 이전 `Planet` 열거형의 변형된 버전입니다:
228 |
229 | ```swift
230 | enum Planet: Int {
231 | case mercury = 1, venus, earth, mars, jupiter, saturn, uranus, neptune
232 | }
233 | ```
234 |
235 | 위의 예제에서 `Planet.mercury` 는 명시적으로 원시값 `1` 을 가지고 `Planet.venus` 는 암시적으로 원시값 `2` 를 가집니다.
236 |
237 | 원시값으로 문자열이 사용될 때 각 케이스의 암시적 값은 케이스의 이름의 문자입니다.
238 |
239 | 아래의 열거형은 각 방향의 이름을 문자열 원시값으로 나타내는 이전 `CompassPoint` 열거형의 변형된 버전입니다:
240 |
241 | ```swift
242 | enum CompassPoint: String {
243 | case north, south, east, west
244 | }
245 | ```
246 |
247 | 위의 예제에서 `CompassPoint.south` 는 `"south"` 의 암시적 원시값을 가지고 있습니다.
248 |
249 | `rawValue` 프로퍼티를 사용하여 열거형 케이스의 원시값에 접근할 수 있습니다:
250 |
251 | ```swift
252 | let earthsOrder = Planet.earth.rawValue
253 | // earthsOrder is 3
254 |
255 | let sunsetDirection = CompassPoint.west.rawValue
256 | // sunsetDirection is "west"
257 | ```
258 |
259 | ### 원시값으로 초기화 \(Initializing from a Raw Value\)
260 |
261 | 원시값 타입으로 열거형을 정의한다면 열거형은 원시값의 타입 \(`rawValue` 라는 파라미터\)을 사용하는 초기화를 자동으로 수신하고 열거형 케이스 또는 `nil` 을 반환합니다. 이 초기화를 이용하여 열거형의 새 인스턴스를 만들 수 있습니다.
262 |
263 | 이 예제는 `7` 원시값으로 천왕성을 식별합니다:
264 |
265 | ```swift
266 | let possiblePlanet = Planet(rawValue: 7)
267 | // possiblePlanet is of type Planet? and equals Planet.uranus
268 | ```
269 |
270 | 그러나 가능한 모든 `Int` 값으로 행성을 찾지 않습니다. 이러한 점 때문에 원시값 초기화는 항상 _옵셔널_ 열거형 케이스를 반환합니다. 위의 예제에서 `possiblePlanet` 은 `Planet?` 또는 "옵셔널 `Planet`" 타입입니다.
271 |
272 | > Note
273 | > 원시값 초기화는 모든 원시값을 열거형 케이스로 반환할 수 없으므로 초기화가 실패할 수 있습니다. 더 자세한 내용은 [실패 가능한 초기화 구문 \(Failable Initializers\)](initialization.md#failable-initializers) 을 참고 바랍니다.
274 |
275 | `11` 의 위치로 행성을 찾는다면 원시값 초기화로 부터 반환된 옵셔널 `Planet` 값은 `nil` 입니다:
276 |
277 | ```swift
278 | let positionToFind = 11
279 | if let somePlanet = Planet(rawValue: positionToFind) {
280 | switch somePlanet {
281 | case .earth:
282 | print("Mostly harmless")
283 | default:
284 | print("Not a safe place for humans")
285 | }
286 | } else {
287 | print("There isn't a planet at position \(positionToFind)")
288 | }
289 | // Prints "There isn't a planet at position 11"
290 | ```
291 |
292 | 이 예제는 `11` 의 원시값으로 행성을 찾기위해 옵셔널 바인딩을 사용합니다. `if let somePlanet = Planet(rawValue: 11)` 구문은 옵셔널 `Planet` 을 생성하고 가져올 수 있다면 옵셔널 `Planet` 의 값을 `somePlanet` 에 설정합니다. 이 경우 `11` 의 위치로 행성을 가져올 수 없으므로 대신에 `else` 구문이 실행됩니다.
293 |
294 | ## 재귀 열거형 \(Recursive Enumerations\)
295 |
296 | _재귀 열거형 \(recursive enumeration\)_ 은 열거형 케이스에 하나 이상의 연관된 값으로 열거형의 다른 인스턴스를 가지고 있는 열거형입니다. 열거형 케이스가 재귀적임을 나타내기 위해 케이스 작성 전에 `indirect` 를 작성하여 컴파일러에게 필요한 간접 \(indirection\) 계층을 삽입하도록 지시합니다.
297 |
298 | 예를 들어 다음은 간단한 산술 표현식을 저장하는 열거형입니다:
299 |
300 | ```swift
301 | enum ArithmeticExpression {
302 | case number(Int)
303 | indirect case addition(ArithmeticExpression, ArithmeticExpression)
304 | indirect case multiplication(ArithmeticExpression, ArithmeticExpression)
305 | }
306 | ```
307 |
308 | 열거형 시작 전에 `indirect` 를 작성하여 연관된 값을 가진 모든 열거형 케이스에 간접을 활성화 할 수 있습니다:
309 |
310 | ```swift
311 | indirect enum ArithmeticExpression {
312 | case number(Int)
313 | case addition(ArithmeticExpression, ArithmeticExpression)
314 | case multiplication(ArithmeticExpression, ArithmeticExpression)
315 | }
316 | ```
317 |
318 | 이 열거형은 숫자, 2개의 표현식의 덧셈, 2개의 표현식의 곱셈의 3가지의 산술 표현식을 저장할 수 있습니다. `addition` 과 `multiplication` 케이스는 산술 표현식인 연관된 값을 가지고 있고 이 연관된 값은 중첩 표현식을 가능하게 해줍니다. 예를 들어 `(5 + 4) * 2` 표현식은 곱셈의 우항은 하나의 숫자를 가지고 있고 좌항은 다른 표현식을 가지고 있습니다. 데이터는 중첩되기 때문에 데이터를 저장하는 열거형도 중첩을 지원해야 합니다. 이것은 열거형은 재귀적이어야 한다는 의미입니다. 아래의 코드는 `(5 + 4) * 2` 에 대해 생성되는 `ArithmeticExpression` 재귀 열거형을 나타냅니다:
319 |
320 | ```swift
321 | let five = ArithmeticExpression.number(5)
322 | let four = ArithmeticExpression.number(4)
323 | let sum = ArithmeticExpression.addition(five, four)
324 | let product = ArithmeticExpression.multiplication(sum, ArithmeticExpression.number(2))
325 | ```
326 |
327 | 재귀 함수는 재귀 구조를 가진 데이터로 작업하는 간단한 방법입니다. 예를 들어 다음은 산술 표현식을 판단하는 함수입니다:
328 |
329 | ```swift
330 | func evaluate(_ expression: ArithmeticExpression) -> Int {
331 | switch expression {
332 | case let .number(value):
333 | return value
334 | case let .addition(left, right):
335 | return evaluate(left) + evaluate(right)
336 | case let .multiplication(left, right):
337 | return evaluate(left) * evaluate(right)
338 | }
339 | }
340 |
341 | print(evaluate(product))
342 | // Prints "18"
343 | ```
344 |
345 | 이 함수는 단순하게 관련된 값을 반환하여 숫자를 판단합니다. 좌항의 식을 판단하고 우항의 식을 판단한 다음에 이를 더하거나 곱하여 덧셈 또는 곱셈을 판단합니다.
346 |
347 |
--------------------------------------------------------------------------------
/language-guide-1/error-handling.md:
--------------------------------------------------------------------------------
1 | # 에러 처리 \(Error Handling\)
2 |
3 | 에러에 응답하고 복구합니다.
4 |
5 | _에러 처리 \(Error handling\)_ 는 프로그램의 에러 조건에서 응답하고 복구하는 프로세스 입니다. Swift는 런타임에 복구 가능한 에러를 던지고 포착하고 전파하고 조작하기 위한 최고 수준의 지원을 제공합니다.
6 |
7 | 일부 작업은 항상 실행을 완료하거나 유용한 출력을 생성한다고 보장되지 않습니다. 옵셔널은 값이 없음을 나타내는데 사용되지만 작업이 실패할 경우 코드가 그에 따라 응답할 수 있도록 에러의 원인을 이해하는 것이 유용한 경우가 많습니다.
8 |
9 | 예를 들어 디스크의 파일에서 데이터를 읽고 처리하는 작업을 생각해 봅시다. 지정된 위치에 파일이 존재하지 않거나 파일에 읽기 권한이 없거나 적절한 형식으로 인코딩 되지 않는 것을 포함하여 작업이 실패할 수 있는 많은 방법이 있습니다. 이러한 다른 상황을 구분하면 프로그램에서 일부 에러를 해결하고 해결할 수 없는 에러를 전달할 수 있습니다.
10 |
11 | > Note
12 | > Swift에서 에러 처리는 Cocoa와 Objective-C에 `NSError` 를 사용하는 에러 처리 패턴과 상호 운용됩니다. 더많은 정보는 [Swift에서 Cocoa 에러 처리 \(Handling Cocoa Errors in Swift\)](https://developer.apple.com/documentation/swift/cocoa_design_patterns/handling_cocoa_errors_in_swift) 를 참고 바랍니다.
13 |
14 | ## 에러 표현과 던지기 \(Representing and Throwing Errors\)
15 |
16 | Swift에서 에러는 `Error` 프로토콜에 준수하는 타입의 값으로 표현됩니다. 이 빈 프로토콜은 에러를 처리하는 것에 대해 사용될 수 있음을 나타냅니다.
17 |
18 | Swift 열거형은 관련된 에러 조건의 그룹을 모델링하는데 특히 적합하며 관련값을 사용하여 에러의 특성에 대한 추가 정보를 전달할 수 있습니다. 예를 들어 다음은 게임 내에서 자동 판매기를 작동하는 에러 조건을 나타내는 방법입니다:
19 |
20 | ```swift
21 | enum VendingMachineError: Error {
22 | case invalidSelection
23 | case insufficientFunds(coinsNeeded: Int)
24 | case outOfStock
25 | }
26 | ```
27 |
28 | 에러가 발생하면 예상치 못한 일이 발생하여 정상적인 흐름을 계속할 수 없음을 나타낼 수 있습니다. `throw` 구문을 사용하여 에러를 발생 시킵니다. 예를 들어 아래의 코드는 자동 판매기에 5개의 코인이 더 필요하다고 에러를 발생 시킵니다:
29 |
30 | ```swift
31 | throw VendingMachineError.insufficientFunds(coinsNeeded: 5)
32 | ```
33 |
34 | ## 에러 처리 \(Handling Errors\)
35 |
36 | 에러가 발생할 때 주변 코드의 부분이 에러 처리를 담당해야 합니다. 예를 들어 문제를 수정하거나 다른 방법을 시도하거나 사용자에게 에러를 알리는 방법으로 에러를 처리해야 합니다.
37 |
38 | Swift에서는 에러를 처리하는 4가지 방법이 있습니다. 함수에서 해당 함수를 호출하는 코드로 에러를 전파하거나 `do`-`catch` 구문을 사용하거나 옵셔널 값으로 에러를 처리하거나 에러가 발생하지 않을 것이라고 주장할 수 있습니다. 각 접근은 아래에 설명되어 있습니다.
39 |
40 | 함수에서 에러가 발생하면 프로그램의 흐름이 변경되므로 코드에서 에러가 발생할 수 있는 위치를 신속하게 알 수 있어야 합니다. 코드에서 이러한 위치를 식별하려면 에러가 발생할 수 있는 함수, 메서드, 또는 초기화 구문을 호출하는 코드 이전에 `try` 또는 `try?` 또는 `try!` 키워드를 작성합니다. 이 키워드는 아래에 설명되어 있습니다.
41 |
42 | > Note
43 | > Swift에서 에러 처리는 `try`, `catch` 그리고 `throw` 키워드를 사용하는 다른 언어에서 에러 처리와 유사합니다. Objective-C를 포함하여 많은 언어에서의 예외 처리와 달리 Swift에서 에러 처리는 계산 비용이 많이 드는 프로세스 인 호출 스택 해제가 포함되지 않습니다. 따라서 `throw` 구문의 성능 특성은 `return` 구문의 성능 특성과 비슷합니다.
44 |
45 | ### 던지기 함수를 이용한 에러 전파 \(Propagating Errors Using Throwing Functions\)
46 |
47 | 에러가 발생할 수 있는 함수, 메서드, 또는 초기화 구문을 나타내기 위해 함수의 선언 중 파라미터 뒤에 `throws` 키워드를 작성합니다. `throws` 로 표시된 함수는 _던지기 함수_ 라고 합니다. 함수에 반환 타입이 지정되어 있으면 `throws` 키워드는 반환 화살표 \(`->`\) 전에 작성합니다.
48 |
49 | ```swift
50 | func canThrowErrors() throws -> String
51 |
52 | func cannotThrowErrors() -> String
53 | ```
54 |
55 | 던지기 함수는 내부에서 발생한 에러를 호출된 범위로 전파합니다.
56 |
57 | > Note
58 | > 던지기 함수는 에러를 전파만 할 수 있습니다. 던지기 선언이 되지 않은 함수 내에서 발생된 모든 에러는 함수 내에서 처리되어야 합니다.
59 |
60 | 아래 예제에서 `VendingMachine` 클래스는 요청된 항목이 불가능 하거나 품절이거나 현재 입금액을 초과하는 비용이 있는 경우 적절한 `VendingMachineError` 를 발생하는 `vend(itemNamed:)` 메서드를 가지고 있습니다:
61 |
62 | ```swift
63 | struct Item {
64 | var price: Int
65 | var count: Int
66 | }
67 |
68 | class VendingMachine {
69 | var inventory = [
70 | "Candy Bar": Item(price: 12, count: 7),
71 | "Chips": Item(price: 10, count: 4),
72 | "Pretzels": Item(price: 7, count: 11)
73 | ]
74 | var coinsDeposited = 0
75 |
76 | func vend(itemNamed name: String) throws {
77 | guard let item = inventory[name] else {
78 | throw VendingMachineError.invalidSelection
79 | }
80 |
81 | guard item.count > 0 else {
82 | throw VendingMachineError.outOfStock
83 | }
84 |
85 | guard item.price <= coinsDeposited else {
86 | throw VendingMachineError.insufficientFunds(coinsNeeded: item.price - coinsDeposited)
87 | }
88 |
89 | coinsDeposited -= item.price
90 |
91 | var newItem = item
92 | newItem.count -= 1
93 | inventory[name] = newItem
94 |
95 | print("Dispensing \(name)")
96 | }
97 | }
98 | ```
99 |
100 | `vend(itemNamed:)` 메서드의 구현은 `guard` 구문을 사용하여 메서드를 일찍 종료시키고 스낵 구매 요구사항 중 하나라도 충족하지 않으면 적절한 에러를 발생합니다. `throw` 구문은 프로그램 제어를 즉시 전달하므로 항목은 요구사항이 모두 만족해야만 판매됩니다.
101 |
102 | `vend(itemNamed:)` 메서드는 발생하는 에러를 전파하기 때문에 이 메서드를 호출하는 코드는 `do`-`catch` 구문, `try?` 또는 `try!` 를 사용하여 에러를 처리하거나 계속 전파해야 합니다. 예를 들어 아래 예제에서 `buyFavoriteSnack(person:vendingMachine:)` 은 던지기 함수이며 `vend(itemNamed:)` 메서드에서 발생한 에러는 `buyFavoriteSnack(person:vendingMachine:)` 함수가 호출된 지점까지 전파될 것입니다.
103 |
104 | ```swift
105 | let favoriteSnacks = [
106 | "Alice": "Chips",
107 | "Bob": "Licorice",
108 | "Eve": "Pretzels",
109 | ]
110 | func buyFavoriteSnack(person: String, vendingMachine: VendingMachine) throws {
111 | let snackName = favoriteSnacks[person] ?? "Candy Bar"
112 | try vendingMachine.vend(itemNamed: snackName)
113 | }
114 | ```
115 |
116 | 이 예제에서 `buyFavoriteSnack(person:vendingMachine:)` 함수는 주어진 사람의 좋아하는 스낵을 검색하고 `vend(itemNamed:)` 메서드를 호출하여 그 제품을 구입합니다. `vend(itemNamed:)` 메서드는 에러를 발생할 수 있으므로 `try` 키워드를 앞에 두어 호출됩니다.
117 |
118 | 던지기 초기화 구문은 던지기 함수와 같은 방법으로 에러를 전파할 수 있습니다. 예를 들어 아래의 리스트에서 `PurchasedSnack` 구조체의 초기화 구문은 초기화 프로세스 부분으로 던지기 함수를 호출하고 발생하는 모든 에러를 호출자에게 전파하여 처리합니다.
119 |
120 | ```swift
121 | struct PurchasedSnack {
122 | let name: String
123 | init(name: String, vendingMachine: VendingMachine) throws {
124 | try vendingMachine.vend(itemNamed: name)
125 | self.name = name
126 | }
127 | }
128 | ```
129 |
130 | ### Do-Catch 사용하여 에러 처리 \(Handling Errors Using Do-Catch\)
131 |
132 | `do`-`catch` 구문을 사용하여 코드의 블럭을 실행하여 에러를 처리합니다. 에러가 `do` 절에서 발생되면 `catch` 절과 비교하여 에러를 처리할 수 있는 항목을 결정합니다.
133 |
134 | 다음은 `do`-`catch` 구문의 일반적인 형태입니다:
135 |
136 | ```swift
137 | do {
138 | try <#expression#>
139 | <#statements#>
140 | } catch <#pattern 1#> {
141 | <#statements#>
142 | } catch <#pattern 2#> where <#condition#> {
143 | <#statements#>
144 | } catch <#pattern 3#>, <#pattern 4#> where <#condition#> {
145 | <#statements#>
146 | } catch {
147 | <#statements#>
148 | }
149 | ```
150 |
151 | 처리할 수 있는 에러가 무엇인지 나타내기 위해 `catch` 뒤에 패턴을 작성합니다. `catch` 절이 패턴을 가지고 있지 않다면 이 절은 모든 에러와 일치하고 `error` 라는 이름을 가진 지역 상수로 에러를 바인드 합니다. 자세한 내용은 [패턴 \(Patterns\)](../language-reference/patterns.md) 을 참고 바랍니다.
152 |
153 | 예를 들어 다음 코드는 `VendingMachineError` 열거형에 3가지 모든 케이스에 대해 일치합니다.
154 |
155 | ```swift
156 | var vendingMachine = VendingMachine()
157 | vendingMachine.coinsDeposited = 8
158 | do {
159 | try buyFavoriteSnack(person: "Alice", vendingMachine: vendingMachine)
160 | print("Success! Yum.")
161 | } catch VendingMachineError.invalidSelection {
162 | print("Invalid Selection.")
163 | } catch VendingMachineError.outOfStock {
164 | print("Out of Stock.")
165 | } catch VendingMachineError.insufficientFunds(let coinsNeeded) {
166 | print("Insufficient funds. Please insert an additional \(coinsNeeded) coins.")
167 | } catch {
168 | print("Unexpected error: \(error).")
169 | }
170 | // Prints "Insufficient funds. Please insert an additional 2 coins."
171 | ```
172 |
173 | 위의 예제에서 `buyFavoriteSnack(person:vendingMachine:)` 함수는 에러를 발생할 수 있으므로 `try` 표현식으로 호출됩니다. 에러가 발생하면 실행이 즉시 `catch` 절로 전송되어 전파가 계속 될 것인지 여부를 결정합니다. 패턴이 일치하지 않으면 에러는 마지막 `catch` 절에 의해 포착되고 지역 `error` 상수에 바인딩 됩니다. 에러가 발생하지 않으면 `do` 구문에 나머지 구문이 실행됩니다.
174 |
175 | `catch` 절은 `do` 절에서 발생할 수 있는 모든 에러를 처리할 필요는 없습니다. `catch` 절이 에러를 처리하지 않으면 에러는 주변에 전파합니다. 그러나 전파된 에러는 _일부_ 주변 범위에서 처리되어야 합니다. 던지지 않는 함수에서는 `do`-`catch` 구문에서 에러를 처리해야 합니다. 던지는 함수에서는 `do`-`catch` 구문이나 호출자가 에러를 처리해야 합니다. 에러가 처리되지 않고 범위의 최상위로 전파되면 런타임 에러를 발생합니다.
176 |
177 | 예를 들어 위의 예제는 `VendingMachineError` 가 아닌 모든 에러가 호출 함수에서 포착되도록 작성할 수 있습니다:
178 |
179 | ```swift
180 | func nourish(with item: String) throws {
181 | do {
182 | try vendingMachine.vend(itemNamed: item)
183 | } catch is VendingMachineError {
184 | print("Couldn't buy that from the vending machine.")
185 | }
186 | }
187 |
188 | do {
189 | try nourish(with: "Beet-Flavored Chips")
190 | } catch {
191 | print("Unexpected non-vending-machine-related error: \(error)")
192 | }
193 | // Prints "Couldn't buy that from the vending machine."
194 | ```
195 |
196 | `nourish(with:)` 함수에서 `vend(itemNamed:)` 가 `VendingMachineError` 열거형에 케이스 중 하나의 에러를 발생하면 `nourish(with:)` 는 메세지를 출력하여 에러를 처리합니다. 그렇지 않으면 `nourish(with:)` 는 호출 부분으로 에러를 전파합니다. 이 에러는 일반적인 `catch` 절에 의해 포착됩니다.
197 |
198 | 연관된 에러를 포착하기 위한 다른 방법은 콤마로 구분하여 `catch` 다음에 리스트 형식으로 작성하는 것입니다. 예를 들어:
199 |
200 | ```swift
201 | func eat(item: String) throws {
202 | do {
203 | try vendingMachine.vend(itemNamed: item)
204 | } catch VendingMachineError.invalidSelection, VendingMachineError.insufficientFunds, VendingMachineError.outOfStock {
205 | print("Invalid selection, out of stock, or not enough money.")
206 | }
207 | }
208 | ```
209 |
210 | `eat(item:)` 함수는 포착할 자동 판매기 에러를 나열하며 에러 텍스트는 해당 리스트의 항목에 해당합니다. 리스트화 된 3가지 에러 중 어떤 에러가 발생하면 이 `catch` 절은 메세지를 출력하여 처리합니다. 나중에 추가될 수 있는 에러를 포함하여 다른 에러는 주변 범위로 전파됩니다.
211 |
212 | ### 에러를 옵셔널 값을 변환 \(Converting Errors to Optional Values\)
213 |
214 | 에러를 옵셔널 값으로 변환하여 처리하기 위해 `try?` 를 사용합니다. `try?` 표현식을 평가하는 동안 에러가 발생되면 이 표현식의 값은 `nil` 입니다. 예를 들어 아래 코드에서 `x` 와 `y` 는 같은 값을 가지고 동작합니다:
215 |
216 | ```swift
217 | func someThrowingFunction() throws -> Int {
218 | // ...
219 | }
220 |
221 | let x = try? someThrowingFunction()
222 |
223 | let y: Int?
224 | do {
225 | y = try someThrowingFunction()
226 | } catch {
227 | y = nil
228 | }
229 | ```
230 |
231 | `someThrowingFunction()` 이 에러를 발생하면 `x` 와 `y` 의 값은 `nil` 입니다. 그렇지 않으면 `x` 와 `y` 의 값은 반환된 함수 값입니다. `x` 와 `y` 는 `someThrowingFunction()` 이 반환하는 타입의 옵셔널 입니다. 여기서 함수는 정수를 반환하므로 `x` 와 `y` 는 옵셔널 정수입니다.
232 |
233 | `try?` 를 사용하면 모든 에러를 같은 방식으로 처리하려는 경우 간결한 에러 처리 코드를 작성할 수 있습니다. 예를 들어 아래의 코드는 여러 접근방식을 사용하여 데이터를 가져오거나 모든 접근방식이 실패하면 `nil` 을 반환합니다.
234 |
235 | ```swift
236 | func fetchData() -> Data? {
237 | if let data = try? fetchDataFromDisk() { return data }
238 | if let data = try? fetchDataFromServer() { return data }
239 | return nil
240 | }
241 | ```
242 |
243 | ### 에러 전파 비활성화 \(Disabling Error Propagation\)
244 |
245 | 가끔 던지는 함수 또는 메서드가 실제로 런타임 에러를 발생하지 않는다는 사실을 알고 있습니다. 이러한 경우 표현식 전에 에러 전파를 비활성화 하기 위해 `try!` 를 작성할 수 있고 에러를 발생하지 않는다고 호출을 래핑할 수 있습니다. 에러가 발생한다면 런타임 에러가 발생합니다.
246 |
247 | 예를 들어 다음의 코드는 주어진 경로의 이미지를 로드하거나 이미지를 로드할 수 없을 때는 에러를 발생하는 `loadImage(atPath:)` 함수를 사용합니다. 이러한 경우 이미지는 이미지는 애플리케이션과 함께 제공되고 런타임에 에러가 발생하지 않으므로 에러 전파를 비활성화 하는 것이 적절합니다.
248 |
249 | ```swift
250 | let photo = try! loadImage(atPath: "./Resources/John Appleseed.jpg")
251 | ```
252 |
253 | ## 에러 타입 지정 (Specifying the Error Type)
254 |
255 | 위에 모든 예제에서 사용하는 에러 처리의 방법에서
256 | 에러는
257 | `Error` 프로토콜을 준수하는 타입의 값입니다.
258 | 이러한 접근방식은
259 | 코드가 실행되는 동안 발생하는 모든 오류와
260 | 다른 곳에서 전파된 에러에 대해
261 | 미리 알 수 없습니다.
262 | 이것은 오류가 시간이 지남에 따라 변할 수 있음을 나타냅니다.
263 | 의존성을 사용하는 라이브러리를 포함하여
264 | 새로운 라이브러리는
265 | 새로운 에러를 던질 수 있고,
266 | 개발 또는 테스트 중에 보여지지 않는 실패 모드를 나타낼 수 있습니다.
267 | 위의 예제에서 에러를 처리하는 코드는
268 | 특정 `catch` 구문이 없는
269 | 에러 처리를 위해 기본 케이스를 포함합니다.
270 |
271 | 대부분의 Swift 코드는 던지는 에러에 대해 타입을 지정하지 않습니다.
272 | 그러나,
273 | 다음과 같은 특별한 경우에
274 | 특정 타입의 에러로 제한할 수 있습니다:
275 |
276 | - 동적 메모리 할당을 지원하지 않는
277 | 임베디드 시스템에서 코드를 실행하는 경우입니다.
278 | `any Error` 또는 다른 박스형 프로토콜 타입의 인스턴스는
279 | 에러를 저장히기위해 런타임 때 메모리에 할당해야 합니다.
280 | 반대로,
281 | 특정 타입의 에러를 발생하려면
282 | Swift 는 에러에 대한 힙 할당을 피할 수 있습니다.
283 |
284 | - 에러가 라이브러리 처럼 일부 코드를 상세히 구현하고,
285 | 인터페이스의 부분이 아닌 경우입니다.
286 | 에러는 라이브러리에서만 발생하고,
287 | 다른 의존성이나 라이브러리의 클라이언트에서 발생하지 않으므로,
288 | 가능한 모든 실패 목록을 만들 수 있습니다.
289 | 그리고 에러는 라이브러리의 세부 구현내용이므로,
290 | 라이브러리 내에서 처리됩니다.
291 |
292 | - 코드에서 클로저 인수를 가지고
293 | 클로저로 부터 에러를 전파하는 함수와 같이
294 | 제너릭 파라미터에 의해 전파되는 에러의 경우입니다.
295 | 특정 에러 타입을 전파하는 것과
296 | `rethrows` 를 사용하는 것에 대한 비교는
297 | [다시 던지는 함수와 메서드 (Rethrowing Functions and Methods)](../language-reference/declarations.md#다시-던지는-함수와-메서드-rethrowing-functions-and-methods) 를 참고 바랍니다.
298 |
299 | 예를 들어,
300 | 평점을 요약하고
301 | 다음의 에러 타입을 사용한다고 생각해 봅시다.
302 |
303 | ```swift
304 | enum StatisticsError: Error {
305 | case noRatings
306 | case invalidRating(Int)
307 | }
308 | ```
309 |
310 | 함수는 에러로 `StatisticsError` 값만 던지는 것을 지정하기 위해,
311 | 함수를 선언할 때
312 | `throws` 대신에 `throws(StatisticsError)` 를 작성합니다.
313 | 이 구문은 선언에서 `throws` 다음에 에러 타입을 작성하기 때문에
314 | *타입이 지정된 던기지 (typed throws)* 라고 부릅니다.
315 | 예를 들어,
316 | 아래의 함수는 에러로 `StatisticsError` 값을 던집니다.
317 |
318 | ```swift
319 | func summarize(_ ratings: [Int]) throws(StatisticsError) {
320 | guard !ratings.isEmpty else { throw .noRatings }
321 |
322 | var counts = [1: 0, 2: 0, 3: 0]
323 | for rating in ratings {
324 | guard rating > 0 && rating <= 3 else { throw .invalidRating(rating) }
325 | counts[rating]! += 1
326 | }
327 |
328 | print("*", counts[1]!, "-- **", counts[2]!, "-- ***", counts[3]!)
329 | }
330 | ```
331 |
332 | 위 코드에서,
333 | `summarize(_:)` 함수는 1 에서 3을 나타내는
334 | 평점의 목록을 요약합니다.
335 | 이 함수는 입력이 올바르지 않으면 `StatisticsError` 의 인스턴스를 던집니다.
336 | 위 코드에서 함수의 에러 타입은 이미 정의되었으므로,
337 | 에러를 던질 때 타입을 생략합니다.
338 | 이와 같이 함수에서 에러가 발생할면
339 | `throw StatisticsError.noRatings` 로 작성하는 대신,
340 | `throw .noRatins` 로 짧게 작성할 수 있습니다.
341 |
342 | 함수의 시작 부분에 에러 타입을 지정해서 작성하면,
343 | Swift 는 다른 에러 타입을 던지는지 확인합니다.
344 | 예를 들어,
345 | 이 챕터의 위 예제에서 `summarize(_:)` 함수에
346 | `VendingMachineError` 를 사용하면,
347 | 코드는 컴파일 때 에러가 발생합니다.
348 |
349 | 일반적인 던지는 함수내에서
350 | 타입이 지정된 던지기를 사용하는 함수를 호출할 수 있습니다:
351 |
352 | ```swift
353 | func someThrowingFunction() throws {
354 | let ratings = [1, 2, 3, 2, 2, 1]
355 | try summarize(ratings)
356 | }
357 | ```
358 |
359 | 위 코드에서 `someThrowingFunction()` 에서 에러 타입을 지정하지 않아,
360 | `any Error` 를 던집니다.
361 | `throws(any Error)` 로 명시적으로 에러 타입을 작성할 수도 있습니다;
362 | 아래 코드는 위 코드와 동일합니다:
363 |
364 | ```swift
365 | func someThrowingFunction() throws(any Error) {
366 | let ratings = [1, 2, 3, 2, 2, 1]
367 | try summarize(ratings)
368 | }
369 | ```
370 |
371 | 이 코드에서,
372 | `someThrowingFunction()` 은 `summarize(_:)` 에서 던지는 모든 에러를 전파합니다.
373 | `summarize(_:)` 에서 발생하는 에러는 `StatisticsError` 값이며,
374 | `someThrowingFunction()` 에 유효한 에러입니다.
375 |
376 | `Never` 의 반환 타입으로 반환하지 않는 함수를 작성할 수 있는 것처럼,
377 | 절대 에러를 던지지 않는 `throws(Never)` 로 함수를 작성할 수 있습니다:
378 |
379 | ```swift
380 | func nonThrowingFunction() throws(Never) {
381 | // ...
382 | }
383 | ```
384 |
385 | 이 함수는 던지기 위해 `Never` 타입의 값을 생성할 수 없으므로,
386 | 에러를 던질 수 없습니다.
387 |
388 | 함수의 에러 타입을 지정하는 것 외에도,
389 | `do`-`catch` 구문에 에러 타입을 지정하여 작성할 수도 있습니다.
390 | 예를 들어:
391 |
392 | ```swift
393 | let ratings = []
394 | do throws(StatisticsError) {
395 | try summarize(ratings)
396 | } catch {
397 | switch error {
398 | case .noRatings:
399 | print("No ratings available")
400 | case .invalidRating(let rating):
401 | print("Invalid rating: \(rating)")
402 | }
403 | }
404 | // Prints "No ratings available"
405 | ```
406 |
407 | 이 코드에서,
408 | `do throws(StatisticsError)` 를 작성하는 것은
409 | `do`-`catch` 구문에서 에러로 `StatisticsError` 값을 발생합니다.
410 | 다른 `do`-`catch` 구문과 같이,
411 | `catch` 구문은 가능한 모든 에러를 처리하거나
412 | 주변에 처리되지 않은 에러에 대해 전파합니다.
413 | 이 코드는 `switch` 구문을 사용하여
414 | 모든 에러를 처리합니다.
415 | 패턴을 가지지 않는 다른 `catch` 구문과 같이
416 | 이 구문은 모든 에러와 일치시키고
417 | `error` 라는 이름의 지역 상수에 바인딩 합니다.
418 | `do`-`catch` 구문은 `StatisticsError` 값을 던지므로,
419 | `error` 는 `StatisticsError` 타입의 값입니다.
420 |
421 | 위의 `catch` 구문은 가능한 에러를 일치시키고 처리하기 위해
422 | `switch` 구문을 사용합니다.
423 | 에러 처리 코드없이 `StatisticsError` 에 새로운 케이스를 추가하면,
424 | Swift 는 `switch` 구문이 완전하기 않기 때문에
425 | 에러가 발생합니다.
426 | 자체 에러를 모두 처리하는 라이브러리의 경우에,
427 | 이러한 접근방식을 사용하여 새로운 에러를 처리하기 위한
428 | 새로운 코드를 가져오도록 할 수 있습니다.
429 |
430 | 함수 또는 `do` 블럭에서 하나의 타입으로 에러를 던지면,
431 | Swift 는 타입이 지정된 던지기를 사용하는 코드라고 추론합니다.
432 | 이 짧은 구문을 사용하면,
433 | 위 예제에서 `do`-`catch` 를 아래와 같이 작성할 수 있습니다:
434 |
435 | ```swift
436 | let ratings = []
437 | do {
438 | try summarize(ratings)
439 | } catch {
440 | switch error {
441 | case .noRatings:
442 | print("No ratings available")
443 | case .invalidRating(let rating):
444 | print("Invalid rating: \(rating)")
445 | }
446 | }
447 | // Prints "No ratings available"
448 | ```
449 |
450 | 위 `do`-`catch` 블럭에서 에러 타입을 지정하지 않지만,
451 | Swift 는 `StatisticsError` 를 던진다고 추론합니다.
452 | Swift 가 타입이 지정된 던지기로 추론하는 것을 방지하기 위해
453 | `throws(any Error)` 를 명시적으로 작성할 수 있습니다.
454 |
455 | ## 정리 작업 지정 \(Specifying Cleanup Actions\)
456 |
457 | 코드의 현재 블럭이 종료되기 직전에 어떠한 작업을 수행하려면 `defer` 구문을 사용합니다. 이 구문을 사용하여 에러가 발생하여 종료되거나 `return` 또는 `break` 와 같은 구문에 의해 종료되는 방식에 상관없이 필요한 정리를 수행할 수 있습니다. 예를 들어 `defer` 구문을 사용하여 파일 설명자가 닫히고 수동으로 할당된 메모리가 해제되도록 할 수 있습니다.
458 |
459 | `defer` 구문은 현재 범위가 종료될 때까지 실행을 연기합니다. 이 구문은 `defer` 키워드와 나중에 실행될 구문으로 구성되어 있습니다. 지연된 구문은 `break` 또는 `return` 구문과 같이 구문의 밖으로 제어를 이동하거나 에러를 발생시키는 코드를 포함할 수 없습니다. 지연된 동작은 소스 코드에 작성된 순서와 반대로 실행됩니다. 즉 첫번째 `defer` 구문의 코드는 마지막에 실행되고 두번째 `defer` 구문의 코드는 마지막에서 두번째로 실행되는 식입니다. 소스 코드의 마지막 `defer` 구문은 마지막에 실행합니다.
460 |
461 | ```swift
462 | func processFile(filename: String) throws {
463 | if exists(filename) {
464 | let file = open(filename)
465 | defer {
466 | close(file)
467 | }
468 | while let line = try file.readline() {
469 | // Work with the file.
470 | }
471 | // close(file) is called here, at the end of the scope.
472 | }
473 | }
474 | ```
475 |
476 | 위의 예제는 `open(_:)` 함수에 `close(_:)` 에 대한 호출이 있는지 확인하기 위해 `defer` 구문을 사용합니다.
477 |
478 | 에러 처리 코드가 포함되어 있지 않아도 `defer` 구문을 사용할 수 있습니다.
479 | 더 자세한 내용은 [연기된 동작 (Deferred Actions)](control-flow.md#연기된-동작-deferred-actions) 을 참고 바랍니다.
480 |
481 |
--------------------------------------------------------------------------------
/language-guide-1/extensions.md:
--------------------------------------------------------------------------------
1 | # 확장 \(Extensions\)
2 |
3 | 기존 타입에 기능을 추가합니다.
4 |
5 | _확장 \(Extensions\)_ 은 기존의 클래스, 구조체, 열거형, 또는 프로토콜 타입에 새로운 기능을 추가합니다. 이것은 기존 소스 코드에 접근 권한이 없는 타입을 확장하는 기능이 포함됩니다 \(_소급 모델링 \(retroactive modeling\)_ 이라고 함\). 확장은 Objective-C의 카테고리와 유사합니다 \(Objective-C 카테고리와 달리 Swift 확장은 이름이 없습니다\).
6 |
7 | Swift에서 확장은 다음을 수행할 수 있습니다:
8 |
9 | * 계산된 인스턴스 프로퍼티와 계산된 타입 프로퍼티 추가
10 | * 인스턴스 메서드와 타입 메서드 정의
11 | * 새로운 초기화 구문 제공
12 | * 서브 스크립트 정의
13 | * 새로운 중첩된 타입 정의와 사용
14 | * 기존 타입이 프로토콜을 준수하도록 함
15 |
16 | Swift에서 프로토콜을 확장하여 그것의 요구사항의 구현을 제공하거나 준수하는 타입의 기능을 추가할 수도 있습니다. 더 자세한 내용은 [프로토콜 확장 \(Protocol Extensions\)](protocols.md#protocol-extensions) 을 참고 바랍니다.
17 |
18 | > Note
19 | > 확장은 타입에 새로운 기능을 추가할 수 있지만 기존 기능을 재정의 할 수는 없습니다.
20 |
21 | ## 확장 구문 \(Extension Syntax\)
22 |
23 | `extension` 키워드를 사용하여 확장을 선언합니다:
24 |
25 | ```swift
26 | extension SomeType {
27 | // new functionality to add to SomeType goes here
28 | }
29 | ```
30 |
31 | 확장은 하나 이상의 프로토콜을 채택하여 기존 타입을 확장할 수 있습니다. 프로토콜 준수를 추가할 때 클래스 또는 구조체를 작성하는 것과 동일한 방법으로 프로토콜 이름을 작성합니다:
32 |
33 | ```swift
34 | extension SomeType: SomeProtocol, AnotherProtocol {
35 | // implementation of protocol requirements goes here
36 | }
37 | ```
38 |
39 | 이러한 방법에 대한 자세한 설명은 [확장으로 프로토콜 준수 추가 \(Adding Protocol Conformance with an Extension\)](protocols.md#adding-protocol-conformance-with-an-extension) 를 참고 바랍니다.
40 |
41 | 확장은 [제너릭 타입 확장 \(Extending a Generic Type\)](generics.md#extending-a-generic-type) 에 설명된대로 기존 일반 타입을 확장하기 위해 사용될 수 있습니다. [제너릭 Where 절이 있는 확장 \(Extensions with a Generic Where Clause\)](generics.md#where-extensions-with-a-generic-where-clause) 에 설명된 대로 일반 타입을 확장하여 조건부로 기능을 추가할 수도 있습니다.
42 |
43 | > Note
44 | > 기존 타입에 새로운 기능을 추가하기 위해 확장을 정의한다면 새로운 기능은 확장이 정의되기 전에 생성 된 기존 인스턴스에서도 사용 가능합니다.
45 |
46 | ## 계산된 프로퍼티 \(Computed Properties\)
47 |
48 | 확장은 기존 타입에 계산된 인스턴스 프로퍼티와 계산된 타입 프로퍼티를 추가할 수 있습니다. 이 예제는 거리 단위 작업에 필요한 최소한의 지원을 제공하기 위해 Swift의 `Double` 타입에 5개의 계산된 인스턴스 프로퍼티를 추가합니다:
49 |
50 | ```swift
51 | extension Double {
52 | var km: Double { return self * 1_000.0 }
53 | var m: Double { return self }
54 | var cm: Double { return self / 100.0 }
55 | var mm: Double { return self / 1_000.0 }
56 | var ft: Double { return self / 3.28084 }
57 | }
58 | let oneInch = 25.4.mm
59 | print("One inch is \(oneInch) meters")
60 | // Prints "One inch is 0.0254 meters"
61 | let threeFeet = 3.ft
62 | print("Three feet is \(threeFeet) meters")
63 | // Prints "Three feet is 0.914399970739201 meters"
64 | ```
65 |
66 | 이 계산된 프로퍼티는 특정 길이의 단위로 `Double` 값을 표현합니다. 계산된 프로퍼티로 구현 되었지만 이러한 프로퍼티의 이름은 거리 변환을 수행하기 위해 해당 리터럴 값을 사용하는 방법으로 부동 소수점 값에 점 구문을 사용할 수 있습니다.
67 |
68 | 이 예제에서 `1.0` 의 `Double` 값은 "1 미터" 로 표시됩니다. `1.m` 표현식은 `Double` 값의 `1.0` 을 계산한 것으로 간주되므로 `m` 계산된 프로퍼티가 `self` 를 반환하는 이유입니다.
69 |
70 | 다른 단위는 미터로 계산된 값으로 표현되기 위해 변환을 요구합니다. 1 킬로미터는 1,000 미터와 같으므로 `km` 계산된 프로퍼티는 미터로 표현된 숫자로 변환하기 위해 `1_000.00` 의 값을 곱합니다. 유사하게 3.28084 피트는 1 미터 이므로 `ft` 계산된 프로퍼티는 피트를 미터로 변환하기 위해 `3.28084` 의 `Double` 값으로 나눕니다.
71 |
72 | 이 프로퍼티는 읽기전용 계산된 프로퍼티 이므로 간결성을 위해 `get` 키워드 없이 표현됩니다. 반환값은 `Double` 타입의 값이고 `Double` 이 허용되는 수학적 계산 내에서는 사용될 수 있습니다:
73 |
74 | ```swift
75 | let aMarathon = 42.km + 195.m
76 | print("A marathon is \(aMarathon) meters long")
77 | // Prints "A marathon is 42195.0 meters long"
78 | ```
79 |
80 | > Note
81 | > 확장은 새로운 계산된 프로퍼티를 추가할 수 있지만 저장된 프로퍼티나 기존 프로퍼티에 프로퍼티 관찰자를 추가할 수 없습니다.
82 |
83 | ## 초기화 구문 \(Initializers\)
84 |
85 | 확장은 기존 타입에 새로운 초기화 구문을 추가할 수 있습니다. 이것은 초기화 구문 파라미터로 고유한 사용자 정의 타입을 받아들이기 위해 다른 타입을 확장하거나 타입의 기존 구현의 부분으로 포함되지 않는 추가 초기화 옵션을 제공할 수 있습니다.
86 |
87 | 확장은 클래스에 새로운 편의 초기화 구문을 추가할 수 있지만 새로운 지정된 초기화 구문이나 초기화 해제 구문은 클래스에 추가할 수 없습니다. 지정된 초기화 구문과 초기화 해제 구문은 항상 기존 클래스 구현에 의해 제공되어야 합니다.
88 |
89 | 모든 저장된 프로퍼티에 기본값을 제공하고 모든 사용자 정의 초기화 구문을 정의하지 않은 값 타입으로 초기화 구문을 추가하기 위해 확장을 사용하면 확장의 초기화 구문 내에서 값 타입에 대해 기본 초기화 구문과 멤버별 초기화 구문을 호출할 수 있습니다. [값 타입을 위한 초기화 구문 위임 \(Initializer Delegation for Value Types\)](initialization.md#initializer-delegation-for-value-types) 에서 설명한대로 값 타입의 기존 구현의 부분으로 초기화 구문을 작성한 경우에는 해당되지 않습니다.
90 |
91 | 다른 모듈에서 선언된 구조체에 초기화 구문을 추가하기 위해 확장을 사용한다면 새로운 초기화 구문은 정의한 모듈에서 초기화 구문을 호출할 때까지 `self` 를 접근할 수 없습니다.
92 |
93 | 아래의 예제는 사각형을 나타내기 위해 사용자 정의 `Rect` 구조체를 정의합니다. 이 예제는 모든 프로퍼티에 `0.0` 의 기본값을 제공하는 `Size` 와 `Point` 라는 2개의 구조체도 정의합니다:
94 |
95 | ```swift
96 | struct Size {
97 | var width = 0.0, height = 0.0
98 | }
99 | struct Point {
100 | var x = 0.0, y = 0.0
101 | }
102 | struct Rect {
103 | var origin = Point()
104 | var size = Size()
105 | }
106 | ```
107 |
108 | `Rect` 구조체는 모든 프로퍼티에 대해 기본값을 제공하므로 [기본 초기화 구문 \(Default Initializers\)](initialization.md#default-initializers) 에서 설명한대로 자동으로 기본 초기화 구문과 멤버별 초기화 구문을 받습니다. 이 초기화 구문은 새로운 `Rect` 인스턴스를 생성하기 위해 사용될 수 있습니다:
109 |
110 | ```swift
111 | let defaultRect = Rect()
112 | let memberwiseRect = Rect(origin: Point(x: 2.0, y: 2.0),
113 | size: Size(width: 5.0, height: 5.0))
114 | ```
115 |
116 | 특정 중심점과 크기를 가지는 초기화 구문을 제공하기 위해 `Rect` 구조체를 확장할 수 있습니다:
117 |
118 | ```swift
119 | extension Rect {
120 | init(center: Point, size: Size) {
121 | let originX = center.x - (size.width / 2)
122 | let originY = center.y - (size.height / 2)
123 | self.init(origin: Point(x: originX, y: originY), size: size)
124 | }
125 | }
126 | ```
127 |
128 | 이 새로운 초기화 구문은 제공된 `center` 점과 `size` 값을 기반으로 적절한 원점을 계산하는 것으로 시작합니다. 그러면 이 초기화 구문은 적절한 프로퍼티에 새로운 원점과 크기 값을 저장하는 구조체의 자동 멤버별 초기화 구문 `init(origin:size:)` 를 호출합니다:
129 |
130 | ```swift
131 | let centerRect = Rect(center: Point(x: 4.0, y: 4.0),
132 | size: Size(width: 3.0, height: 3.0))
133 | // centerRect's origin is (2.5, 2.5) and its size is (3.0, 3.0)
134 | ```
135 |
136 | > Note
137 | > 확장으로 새로운 초기화 구문을 제공하면 초기화 구문이 완료되면 각 인스턴스가 완전히 초기화 되었는지 확인해야 합니다.
138 |
139 | ## 메서드 \(Methods\)
140 |
141 | 확장은 기존 타입에 새로운 인스턴스 메서드와 타입 메서드를 추가할 수 있습니다. 아래 예제는 `Int` 타입으로 `repetitions` 라는 새로운 인스턴스 메서드를 추가합니다:
142 |
143 | ```swift
144 | extension Int {
145 | func repetitions(task: () -> Void) {
146 | for _ in 0.. Void` 타입의 인수를 가집니다.
154 |
155 | 이 확장을 정의한 후에 여러번 작업을 수행하기 위해 모든 정수로 `repetitions(task:)` 메서드를 호출할 수 있습니다:
156 |
157 | ```swift
158 | 3.repetitions {
159 | print("Hello!")
160 | }
161 | // Hello!
162 | // Hello!
163 | // Hello!
164 | ```
165 |
166 | ### 인스턴스 메서드 변경 \(Mutating Instance Methods\)
167 |
168 | 확장에서 추가된 인스턴스 메서드는 인스턴스 자체로 수정 또는 변경할 수 있습니다. `self` 또는 프로퍼티를 수정하는 구조체와 열거형 메서드는 기존 구현의 변경 메서드와 같이 `mutating` 으로 인스턴스 메서드를 표시해야 합니다.
169 |
170 | 아래 예제는 원래값을 제곱하는 Swift의 `Int` 타입의 `square` 라는 새로운 변경 메서드를 추가합니다:
171 |
172 | ```swift
173 | extension Int {
174 | mutating func square() {
175 | self = self * self
176 | }
177 | }
178 | var someInt = 3
179 | someInt.square()
180 | // someInt is now 9
181 | ```
182 |
183 | ## 서브 스크립트 \(Subscripts\)
184 |
185 | 확장은 기존 타입에 새로운 서브 스크립트를 추가할 수 있습니다. 이 예제는 Swift의 `Int` 타입에 정수 서브 스크립트를 추가합니다. 이 서브 스크립트 `[n]` 은 숫자의 오른쪽 부터 `n` 에 위치하는 자리의 숫자를 반환합니다:
186 |
187 | * `123456789[0]` 은 `9` 를 반환
188 | * `123456789[1]` 은 `8` 을 반환
189 |
190 | 등등:
191 |
192 | ```swift
193 | extension Int {
194 | subscript(digitIndex: Int) -> Int {
195 | var decimalBase = 1
196 | for _ in 0.. 0:
234 | return .positive
235 | default:
236 | return .negative
237 | }
238 | }
239 | }
240 | ```
241 |
242 | 이 예제는 `Int` 에 새로운 중첩된 열거형을 추가합니다. `Kind` 라는 열거형은 특정 정수 표현에 대한 숫자의 종류를 나타냅니다. 명확하게 숫자가 음수, 0, 또는 양수 인지 표현합니다.
243 |
244 | 이 예제는 정수에 대해 적절한 `Kind` 열거형 케이스를 반환하는 `kind` 라는 새로운 계산된 인스턴스 프로퍼티를 `Int` 에 추가합니다.
245 |
246 | 이 중첩된 열거형은 모든 `Int` 값에서 사용될 수 있습니다:
247 |
248 | ```swift
249 | func printIntegerKinds(_ numbers: [Int]) {
250 | for number in numbers {
251 | switch number.kind {
252 | case .negative:
253 | print("- ", terminator: "")
254 | case .zero:
255 | print("0 ", terminator: "")
256 | case .positive:
257 | print("+ ", terminator: "")
258 | }
259 | }
260 | print("")
261 | }
262 | printIntegerKinds([3, 19, -27, 0, -6, 0, 7])
263 | // Prints "+ + - 0 - 0 + "
264 | ```
265 |
266 | `printIntegerKinds(_:)` 함수는 `Int` 값의 배열을 입력 받고 반복합니다. 배열의 각 정수에 대해 함수는 해당 정수의 `kind` 계산된 프로퍼티를 고려하고 적절한 설명을 출력합니다.
267 |
268 | > Note
269 | > `number.kind` 는 `Int.Kind` 타입으로 이미 알고 있습니다. 이러한 점 때문에 모든 `Int.Kind` 케이스 값은 `switch` 구문 내에서 `Int.Kind.negative` 가 아닌 `.negative` 로 짧게 작성될 수 있습니다.
270 |
271 |
--------------------------------------------------------------------------------
/language-guide-1/inheritance.md:
--------------------------------------------------------------------------------
1 | # 상속 \(Inheritance\)
2 |
3 | 기능을 추가 또는 재정의 하기 위한 하위 클래스 입니다.
4 |
5 | 클래스는 다른 클래스에서 메서드, 프로퍼티, 그리고 다른 특성을 _상속 \(inherit\)_ 할 수 있습니다. 클래스가 다른 클래스로 부터 상속될 때, 상속받는 클래스를 _하위 클래스 \(subclass\)_ 라고 하고 상속을 하는 클래스를 _상위 클래스 \(superclass\)_ 라고 합니다. 상속은 Swift에서 다른 타입과 클래스를 구분하는 기본적인 동작입니다.
6 |
7 | Swift에서 클래스는 상위 클래스에 속하는 메서드, 프로퍼티, 그리고 서브 스크립트를 호출하고 접근할 수 있으며 메서드, 프로퍼티, 그리고 서브 스크립트를 동작을 수정하기위해 재정의한 버전을 제공할 수 있습니다. Swift는 재정의에 일치하는 상위 클래스 정의가 있는지 확인하고 재정의가 올바른지 확인하는데 도움을 줍니다.
8 |
9 | 클래스는 프로퍼티의 값이 변경될 때 알려주기 위해 상속된 프로퍼티에 프로퍼티 관찰자를 추가할 수도 있습니다. 프로퍼티 관찰자는 기존 프로퍼티가 저장된 프로퍼티 또는 계산된 프로퍼티로 정의되었는지 상관없이 프로퍼티에 추가될 수 있습니다.
10 |
11 | ## 기본 클래스 정의 \(Defining a Base Class\)
12 |
13 | 다른 클래스에서 상속하지 않은 클래스를 _기본 클래스 \(base class\)_ 라고 합니다.
14 |
15 | > Note
16 | > Swift 클래스는 범용 기본 클래스를 상속하지 않습니다. 상위 클래스 지정 없이 정의한 클래스는 자동적으로 빌드 할 때 기본 클래스가 됩니다.
17 |
18 | 아래 예제는 `Vehicle` 이라는 기본 클래스를 정의합니다. 이 기본 클래스는 `Double` 의 프로퍼티 타입으로 유추되는 `0.0` 의 기본값을 가지는 `currentSpeed` 라는 저장된 프로퍼티를 정의합니다. `currentSpeed` 프로퍼티의 값은 탈 것의 설명을 생성하기 위해 `description` 이라는 읽기전용 계산된 `String` 프로퍼티에 사용됩니다.
19 |
20 | `Vehicle` 기본 클래스는 `makeNoise` 라는 메서드도 정의합니다. 이 메서드는 기본 `Vehicle` 인스턴스에서 실질적으로 아무런 동작을 하지 않지만 후에 `Vehicle` 의 하위 클래스에 의해 사용자화 될 것입니다:
21 |
22 | ```swift
23 | class Vehicle {
24 | var currentSpeed = 0.0
25 | var description: String {
26 | return "traveling at \(currentSpeed) miles per hour"
27 | }
28 | func makeNoise() {
29 | // do nothing - an arbitrary vehicle doesn't necessarily make a noise
30 | }
31 | }
32 | ```
33 |
34 | 타입 이름 뒤에 빈 소괄호를 작성한 _초기화 구문_ 으로 `Vehicle` 의 새로운 인스턴스를 생성합니다:
35 |
36 | ```swift
37 | let someVehicle = Vehicle()
38 | ```
39 |
40 | 새로운 `Vehicle` 인스턴스를 생성하면 탈 것의 현재 속도의 설명을 출력하기 위해 `description` 프로퍼티에 접근할 수 있습니다:
41 |
42 | ```swift
43 | print("Vehicle: \(someVehicle.description)")
44 | // Vehicle: traveling at 0.0 miles per hour
45 | ```
46 |
47 | `Vehicle` 클래스는 임의의 탈 것에 대한 공통 특성을 정의하지만 그 자체로는 많이 사용되지 않습니다. 더 유용하게 사용하기 위해 더 구체적인 탈 것 종류를 설명하기 위해 수정이 필요합니다.
48 |
49 | ## 하위 클래스 \(Subclassing\)
50 |
51 | _하위 클래스 \(Subclassing\)_ 는 기존 클래스를 기반으로 새로운 클래스를 만드는 작업입니다. 하위 클래스는 기존 클래스의 특성을 상속하므로 수정할 수 있습니다. 하위 클래스에 새로운 특성도 추가할 수 있습니다.
52 |
53 | 하위 클래스가 상위 클래스를 가지고 있다는 것을 나타내기 위해 하위 클래스 이름은 상위 클래스 이름 전에 콜론으로 구분하여 작성합니다:
54 |
55 | ```swift
56 | class SomeSubclass: SomeSuperclass {
57 | // subclass definition goes here
58 | }
59 | ```
60 |
61 | 다음의 예제는 `Vehicle` 을 상위 클래스로 가지는 `Bicycle` 이라는 하위 클래스를 정의합니다:
62 |
63 | ```swift
64 | class Bicycle: Vehicle {
65 | var hasBasket = false
66 | }
67 | ```
68 |
69 | 새로운 `Bicycle` 클래스는 `currentSpeed` 와 `description` 프로퍼티와 `makeNoise()` 메서드와 같은 `Vehicle` 의 모든 특성을 자동적으로 얻습니다.
70 |
71 | 상속한 특성 외에도 `Bicycle` 클래스는 `Bool` 타입으로 유추되는 기본값 `false` 인 `hasBasket` 이라는 새로운 저장된 프로퍼티를 정의합니다.
72 |
73 | 기본적으로 생성한 새로운 `Bicycle` 인스턴스는 바구니를 가지고 있지 않습니다. 인스턴스가 생성된 후에 특정 `Bicycle` 인스턴스의 `hasBasket` 프로퍼티를 `true` 로 설정할 수 있습니다:
74 |
75 | ```swift
76 | let bicycle = Bicycle()
77 | bicycle.hasBasket = true
78 | ```
79 |
80 | `Bicycle` 인스턴스의 상속된 `currentSpeed` 프로퍼티를 수정할 수 있고 상속된 `description` 프로퍼티를 조회할 수도 있습니다:
81 |
82 | ```swift
83 | bicycle.currentSpeed = 15.0
84 | print("Bicycle: \(bicycle.description)")
85 | // Bicycle: traveling at 15.0 miles per hour
86 | ```
87 |
88 | 하위 클래스는 그 자체로 하위 클래스화 될 수 있습니다. 다음 예제는 "tandem" 이라는 2개의 안장을 가진 자전거를 위한 `Bicycle` 의 하위 클래스를 생성합니다:
89 |
90 | ```swift
91 | class Tandem: Bicycle {
92 | var currentNumberOfPassengers = 0
93 | }
94 | ```
95 |
96 | `Tandem` 은 `Bicycle` 의 모든 프로퍼티와 메서드를 상속하고 차례로 `Vehicle` 의 모든 프로퍼티와 메서드를 상속합니다. `Tandem` 하위 클래스는 기본값 `0` 인 `currentNumberOfPassengers` 라는 새로운 저장된 프로퍼티도 추가합니다.
97 |
98 | `Tandem` 의 인스턴스를 생성하면 새로운 프로퍼티와 상속된 프로퍼티로 동작할 수 있고 `Vehicle` 로 부터 상속한 읽기전용 `description` 프로퍼티를 조회할 수 있습니다:
99 |
100 | ```swift
101 | let tandem = Tandem()
102 | tandem.hasBasket = true
103 | tandem.currentNumberOfPassengers = 2
104 | tandem.currentSpeed = 22.0
105 | print("Tandem: \(tandem.description)")
106 | // Tandem: traveling at 22.0 miles per hour
107 | ```
108 |
109 | ## 재정의 \(Overriding\)
110 |
111 | 하위 클래스는 상위 클래스에서 상속할 인스턴스 메서드, 타입 메서드, 인스턴스 프로퍼티, 타입 프로퍼티, 또는 서브 스크립트 자체 사용자 구현을 제공할 수 있습니다. 이것을 _재정의 \(overriding\)_ 라고 합니다.
112 |
113 | 상속될 특성을 재정의 하려면 재정의 할 정의 앞에 `override` 키워드를 추가합니다. 이렇게 하면 재정의를 명확하게 제공하고 실수로 일치하는 정의를 제공하지 않도록 합니다. 실수로 재정의하면 예기치 않은 동작을 야기하고 `override` 키워드 없이 재정의하면 코드가 컴파일 될 때 에러를 발생합니다.
114 |
115 | `override` 키워드는 재정의 한 클래스의 상위 클래스 또는 상위 클래스 중 하나에 재정의를 위해 일치하는 선언을 Swift 컴파일러는 체크합니다. 이 체크는 재정의하는 정의가 옳다고 보장합니다.
116 |
117 | ### 상위 클래스 메서드, 프로퍼티, 그리고 서브 스크립트 접근 \(Accessing Superclass Methods, Properties, and Subscripts\)
118 |
119 | 하위 클래스에 메서드, 프로퍼티, 또는 서브 스크립트 재정의를 제공할 때 재정의의 일부로 상위 클래스 구현을 사용하는 것이 유용할 때가 있습니다. 예를 들어 기존 구현의 동작을 구체화 하거나 기존 상속된 변수에 수정된 값을 저장할 수 있습니다.
120 |
121 | 이것이 적절한 경우 `super` 접두어를 사용하여 메서드, 프로퍼티, 또는 서브 스크립트의 상위 클래스 버전을 접근합니다:
122 |
123 | * `someMethod()` 라는 재정의된 메서드는 재정의한 메서드 구현 내에서 `super.someMethod()` 를 호출하여 상위 클래스 버전의 `someMethod()` 를 호출할 수 있습니다.
124 | * `someProperty` 라는 재정의된 프로퍼티는 재정의한 getter 또는 setter 구현 내에서 `super.somProperty` 로 상위 클래스 버전의 `someProperty` 를 접근할 수 있습니다.
125 | * `someIndex` 를 위한 재정의된 서브 스크립트는 재정의한 서브 스크립트 구현 내에서 `super[someIndex]` 로 상위 클래스 버전의 같은 서브 스크립트에 접근할 수 있습니다.
126 |
127 | ### 메서드 재정의 \(Overriding Methods\)
128 |
129 | 상속된 인스턴스 또는 타입 메서드를 재정의하여 하위 클래스 내에서 메서드의 맞춤형 또는 대체 구현을 제공합니다.
130 |
131 | 아래 예제는 `Train` 이라는 `Vehicle` 의 새로운 하위 클래스를 정의합니다. `Vehicle` 을 상속한 `Train` 에 `makeNoise()` 메서드를 재정의합니다:
132 |
133 | ```swift
134 | class Train: Vehicle {
135 | override func makeNoise() {
136 | print("Choo Choo")
137 | }
138 | }
139 | ```
140 |
141 | `Train` 에 새로운 인스턴스를 생성하고 `makeNoise()` 메서드를 호출한다면 `Train` 하위 클래스 버전의 메서드가 호출되는 것을 볼 수 있습니다:
142 |
143 | ```swift
144 | let train = Train()
145 | train.makeNoise()
146 | // Prints "Choo Choo"
147 | ```
148 |
149 | ### 프로퍼티 재정의 \(Overriding Properties\)
150 |
151 | 프로퍼티에 고유한 사용자 정의 getter와 setter를 제공하거나 기본 프로퍼티 값이 변경될 때 재정의 한 프로퍼티가 관찰할 수 있도록 프로퍼티 관찰자를 추가 하기위해 상속된 인스턴스 또는 타입 프로퍼티를 재정의할 수 있습니다.
152 |
153 | #### 프로퍼티 getter와 setter 재정의 \(Overriding Property Getters and Setters\)
154 |
155 | 상속된 프로퍼티가 소스에서 저장된 또는 계산된 프로퍼티로 구현되었는지 여부와 상관없이 _모든_ 상속된 프로퍼티를 재정의 하기위해 사용자 지정 getter와 setter를 제공할 수 있습니다. 상속된 프로퍼티에 저장된 또는 계산된 특성은 하위 클래스에서 알 수 없습니다. 상속된 프로퍼티의 특정 이름과 타입만 알고 있습니다. 컴파일러가 동일한 이름과 타입을 가진 상위 클래스 프로퍼티와 일치하는지 확인할 수 있도록 항상 재정의하는 프로퍼티의 이름과 타입을 모두 명시해야 합니다.
156 |
157 | 하위 클래스에서 getter와 setter를 모두 제공하여 상속된 읽기전용 프로퍼티를 읽기-쓰기 프로퍼티로 표시할 수 있습니다. 그러나 상속된 읽기-쓰기 프로퍼티를 읽기전용 프로퍼티로 표시할 수 없습니다.
158 |
159 | > Note
160 | > 프로퍼티 재정의의 부분으로 setter를 제공하면 getter도 제공해야 합니다. 재정의한 getter 내에서 상속된 프로퍼티의 값을 수정하고 싶지 않다면 `someProperty` 가 재정의하는 프로퍼티의 이름이라면 getter에서 `super.someProperty` 를 반환하면 상속된 값을 간편하게 전달할 수 있습니다.
161 |
162 | 다음의 예제는 `Vehicle` 의 하위 클래스인 `Car` 라는 새로운 클래스를 정의합니다. `Car` 클래스는 기본 정수 값이 `1` 인 `gear` 라는 새로운 저장된 프로퍼티를 가집니다. `Car` 클래스는 현재 기어를 포함한 설명을 제공하기 위해 `Vehicle` 로 부터 상속한 `description` 프로퍼티를 재정의 합니다:
163 |
164 | ```swift
165 | class Car: Vehicle {
166 | var gear = 1
167 | override var description: String {
168 | return super.description + " in gear \(gear)"
169 | }
170 | }
171 | ```
172 |
173 | `description` 프로퍼티의 재정의는 `Vehicle` 클래스의 `description` 프로퍼티를 반환하는 `super.description` 호출로 시작합니다. 그런 다음 `description` 의 `Car` 클래스의 버전은 현재 기어에 대한 정보를 추가합니다.
174 |
175 | `Car` 클래스의 인스턴스를 생성하고 `gear` 와 `currentSpeed` 프로퍼티를 설정하면 `description` 프로퍼티는 `Car` 클래스 내에서 정의한 설명을 반환하는 것을 볼 수 있습니다:
176 |
177 | ```swift
178 | let car = Car()
179 | car.currentSpeed = 25.0
180 | car.gear = 3
181 | print("Car: \(car.description)")
182 | // Car: traveling at 25.0 miles per hour in gear 3
183 | ```
184 |
185 | #### 프로퍼티 관찰자 재정의 \(Overriding Property Observers\)
186 |
187 | 상속된 프로퍼티에 프로퍼티 관찰자를 추가하기 위해 프로퍼티 재정의를 사용할 수 있습니다. 이것은 기존에 구현된 프로퍼티가 어떻든 상관없이 상속된 프로퍼티의 값이 변경될 때 알림을 받을 수 있습니다. 자세한 내용은 [프로퍼티 관찰자 \(Property Observers\)](properties.md#property-observers) 을 참고 바랍니다.
188 |
189 | > Note
190 | > 상속된 저장된 프로퍼티 상수 또는 상속된 읽기전용 계산된 프로퍼티에 프로퍼티 관찰자를 추가할 수 없습니다. 이 프로퍼티의 값은 설정할 수 없으므로 재정의의 부분으로 `willSet` 또는 `didSet` 구현을 제공하기에 적절하지 않습니다.
191 | >
192 | > 같은 프로퍼티에 재정의한 setter와 재정의한 프로퍼티 관찰자를 동시에 제공할 수 없습니다. 프로퍼티의 값이 변경되는 것을 관찰하기 원하고 이미 프로퍼티에 사용자화 setter를 제공하고 있다면 사용자화 setter 내에서 간단하게 값 변경을 관찰할 수 있습니다.
193 |
194 | 다음 예제는 `Car` 의 하위 클래스 인 `AutomaticCar` 라는 새로운 클래스를 정의합니다. `AutomaticCar` 클래스는 현재 속도에 기반하여 적절한 기어를 자동적으로 선택하는 자동 기어박스가 있는 자동차를 표시합니다:
195 |
196 | ```swift
197 | class AutomaticCar: Car {
198 | override var currentSpeed: Double {
199 | didSet {
200 | gear = Int(currentSpeed / 10.0) + 1
201 | }
202 | }
203 | }
204 | ```
205 |
206 | `AutomaticCar` 인스턴스에 `currentSpeed` 프로퍼티를 설정할 때마다 프로퍼티의 `didSet` 관찰자는 새로운 속도에 적절한 기어를 인스턴스의 `gear` 프로퍼티에 설정합니다. 특히 프로퍼티 관찰자는 새로운 `currentSpeed` 값을 `10` 으로 나눈다음 가까운 정수로 내림한 다음 `1` 을 더한 값을 기어로 선택합니다. `35.0` 의 속도는 기어가 `4` 가 됩니다:
207 |
208 | ```swift
209 | let automatic = AutomaticCar()
210 | automatic.currentSpeed = 35.0
211 | print("AutomaticCar: \(automatic.description)")
212 | // AutomaticCar: traveling at 35.0 miles per hour in gear 4
213 | ```
214 |
215 | ## 재정의 방지 \(Preventing Overrides\)
216 |
217 | _final_ 표시를 통해 실수로 메서드, 프로퍼티, 또는 서브 스크립트를 재정의 하는 것을 방지할 수 있습니다. 재정의를 방지하려면 메서드, 프로퍼티, 또는 서브 스크립트의 키워드 전에 `final` 수정자를 작성합니다 \(`final var`, `final func`, `final class func`, `final subscript` 와 같이 작성\).
218 |
219 | 하위 클래스에서 final 메서드, 프로퍼티, 또는 서브 스크립트를 재정의 하면 컴파일 시 에러가 발생합니다. 확장한 클래스에 추가된 메서드, 프로퍼티, 또는 서브 스크립트는 확장의 정의 내에서 final로 표기될 수도 있습니다. 자세한 내용은 [확장 (Extensions)](extensions.md) 을 참고 바랍니다.
220 |
221 | 클래스 정의에 `class` 키워드 전에 `final` 키워드를 표기하여 final로 전체 클래스를 표시할 수 있습니다 \(`final class`\). final 클래스를 하위 클래스하려는 모든 시도는 컴파일 시 에러가 발생합니다.
222 |
223 |
--------------------------------------------------------------------------------
/language-guide-1/memory-safety.md:
--------------------------------------------------------------------------------
1 | # 메모리 안전성 \(Memory Safety\)
2 |
3 | 메모리 접근할 때 충돌을 피하기위해 코드를 구조화합니다.
4 |
5 | 기본적으로 Swift는 코드에서 발생할 안전하지 않은 동작을 방지합니다. 예를 들어 Swift는 변수가 사용되기 전에 초기화 되고 메모리가 할당 해제된 후에는 접근되지 않으며 배열 인덱스는 범위를 벗어난 에러가 있는지 확인합니다.
6 |
7 | Swift는 메모리의 위치를 수정하는 코드가 해당 메모리에 대한 독점 접근 권한을 갖도록 요구함으로써 동일한 메모리 영역에 대해 다중 접근이 충돌나지 않도록 합니다. Swift는 메모리를 자동으로 관리하기 때문에 대부분의 경우에 메모리 접근에 대해 생각할 필요가 없습니다. 그러나 잠재적으로 충돌이 발생할 수 있는 것을 이해해야 작성한 코드가 메모리에 접근 충돌을 피할 수 있습니다. 코드에 충돌이 포함되어 있다면 컴파일이나 런타임 에러가 발생합니다.
8 |
9 | ## 메모리에 충돌하는 접근 이해 \(Understanding Conflicting Access to Memory\)
10 |
11 | 메모리에 접근하는 것은 변수의 값을 설정하거나 함수에 인수를 전달하는 것과 같은 동작을 할 때 코드에서 발생합니다. 예를 들어 다음 코드는 읽기 접근과 쓰기 접근 모두 포함합니다:
12 |
13 | ```swift
14 | // A write access to the memory where one is stored.
15 | var one = 1
16 |
17 | // A read access from the memory where one is stored.
18 | print("We're number \(one)!")
19 | ```
20 |
21 | 메모리에 충돌하는 접근은 코드의 다른 부분이 같은 시간에 메모리의 같은 위치에 접근할 때 발생할 수 있습니다. 같은 시간에 메모리의 위치에 다중 접근은 예측할 수 없거나 일관성 없는 동작이 발생할 수 있습니다. Swift에는 코드의 여러 라인에 걸쳐있는 값을 수정하기 위한 방법이 있어서 수정 중에 값에 접근할 수 있습니다.
22 |
23 | 종이에 쓰여진 예산을 어떻게 업데이트 하는지 생각해 보면 비슷한 문제를 확인할 수 있습니다. 예산을 업데이트 하는 것은 2단계 프로세스 입니다: 먼저 항목들의 이름과 가격을 추가한 다음에 현재 리스트에 있는 항목을 반영하기 위해 총 금액을 변경합니다. 업데이트 전후에 아래 그림과 같이 예산에서 모든 정보를 읽고 올바른 답을 얻을 수 있습니다.
24 |
25 | 
26 |
27 | 예산에 항목을 추가하는 동안 총 금액이 새로 추가된 항목을 반영하기 위해 업데이트 되지 않았기 때문에 임시적으로 유효하지 않은 상태입니다. 항목을 추가하는 동안 총 금액을 읽으면 잘못된 정보가 제공됩니다.
28 |
29 | 이 예제는 또한 메모리에 충돌하는 접근을 수정할 때 발생할 수 있는 문제를 보여줍니다: 때로는 충돌을 수정하는 여러가지 방법이 있으며 어떤 답변이 올바른지 항상 명확하지 않습니다. 이 예제에서 기존 총 금액 또는 업데이트 된 총 금액을 원하는지에 따라 $5 또는 $320이 정답이 될 수 있습니다. 충돌하는 접근을 수정하려면 수행할 작업의 의도를 파악해야 합니다.
30 |
31 | > Note
32 | > 동시 또는 다중 쓰레드 코드를 작성한 경우 메모리 접근 충돌이 익숙한 문제일 수 있습니다. 그러나 여기서 설명한 충돌 접근은 단일 쓰레드에서 발생할 수 있으며 동시 또는 다중 쓰레드 코드를 포함하지 않습니다.
33 | >
34 | > 단일 쓰레드 내에서 메모리 접근이 충돌하는 경우 Swift는 컴파일 이나 런타임 시 에러가 발생합니다. 다중 쓰레드 코드의 경우 [Thread Sanitizer](https://developer.apple.com/documentation/xcode/diagnosing_memory_thread_and_crash_issues_early) 사용하여 쓰레드 간에 충돌하는 접근을 감지할 수 있습니다.
35 |
36 | ### 메모리 접근의 특징 \(Characteristics of Memory Access\)
37 |
38 | 충돌 접근의 맥락에서 고려해야 할 메모리 접근의 3가지 특성이 있습니다: 접근하는 동안 읽기 또는 쓰기 접근인지 여부와 접근된 메모리의 위치입니다. 특히 아래의 조건을 모두 만족하는 2개의 접근이 있다면 충돌이 발생합니다:
39 |
40 | * 두 접근은 모두 읽을 수 없고, 두 접근 모두 atomic 입니다.
41 | * 메모리의 같은 위치에 접근합니다.
42 | * 접근하는 시간이 겹칩니다.
43 |
44 | 읽기와 쓰기 접근 간의 차이는 일반적으로 명확합니다: 쓰기 접근은 메모리의 위치를 변경하지만 읽기 접근은 변경하지 않습니다. 메모리의 위치는 예를 들어 변수, 상수 또는 프로퍼티와 같이 접근 중인 항목을 나타냅니다. 메모리 접근 기간은 순간적이거나 장기적입니다.
45 |
46 | 접근이 *atomic* 이라는 것은
47 | [`Atomic`](https://developer.apple.com/documentation/synchronization/atomic) 또는 [`AtomicLazyReference`](https://developer.apple.com/documentation/synchronization/atomiclazyreference) 의 atomic 연산을 호출하는 경우이거나,
48 | C atomic 연산자만 사용하는 경우를 의미합니다;
49 | 그렇지 않으면 nonatomic 입니다.
50 | C 의 atomic 함수 목록은 `stdatomic(3)` 메뉴얼 페이지에서 확인 가능합니다.
51 |
52 | 접근이 시작되고 종료되기 전에 다른 코드를 실행할 수 없는 경우 접근은 _즉시_ 이루어집니다. 일반적으로 2개의 즉시 접근은 동시에 발생할 수 없습니다. 대부분 메모리 접근은 즉각적입니다. 예를 들어 아래 코드 리스트의 모든 읽기와 쓰기 접근은 즉각적입니다:
53 |
54 | ```swift
55 | func oneMore(than number: Int) -> Int {
56 | return number + 1
57 | }
58 |
59 | var myNumber = 1
60 | myNumber = oneMore(than: myNumber)
61 | print(myNumber)
62 | // Prints "2"
63 | ```
64 |
65 | 그러나 다른 코드 실행에 걸쳐있는 _장기 \(long-term\)_ 접근이라는 메모리 접근 방법은 여러가지 입니다. 즉각 접근 \(instantaneous access\)와 장기 접근 \(long-term access\) 간의 차이점은 장기 접근이 시작되고 종료되기 전에 다른 코드가 실행될 수 있다는 것입니다. 이것을 _오버랩 \(overlap\)_ 이라 합니다. 장기 접근은 다른 장기 접근과 즉각 접근과 오버랩 될 수 있습니다.
66 |
67 | 겹치는 접근은 함수와 메서드에서 in-out 파라미터를 사용하거나 구조체의 변경하는 메서드를 사용하는 코드에 주로 나타납니다. 장기 접근을 사용하는 Swift 코드의 특정 종류는 아래 섹션에서 설명합니다.
68 |
69 | ## In-Out 파라미터에 충돌 접근 \(Conflicting Access to In-Out Parameters\)
70 |
71 | 함수는 모든 in-out 파라미터에 장기 쓰기 접근을 가지고 있습니다. in-out 파라미터에 대한 쓰기 접근은 모든 non-in-out 파라미터가 평가된 후에 시작되고 해당 함수가 호출되는 동안 지속됩니다. In-out 파라미터가 여러개 인 경우 쓰기 접근은 파라미터가 나타나는 순서와 동일한 순서로 시작됩니다.
72 |
73 | 이 장기 쓰기 접근의 결과 중 하나는 범위 규칙과 접근 제어가 허용하더라도 기존에 대한 모든 접근은 충돌을 생성하므로 전달된 원래 변수에 접근할 수 없다는 것입니다. 예를 들어:
74 |
75 | ```swift
76 | var stepSize = 1
77 |
78 | func increment(_ number: inout Int) {
79 | number += stepSize
80 | }
81 |
82 | increment(&stepSize)
83 | // Error: conflicting accesses to stepSize
84 | ```
85 |
86 | 위의 코드에서 `stepSize` 는 전역 변수이고 일반적으로 `increment(_:)` 내에서 접근할 수 있습니다. 그러나 `stepSize` 에 읽기 접근은 `number` 에 쓰기 접근과 오버랩 됩니다. 아래 그림에서 보았듯이 `number` 와 `stepSize` 모두 같은 메모리의 위치를 참조합니다. 읽기와 쓰기 접근은 같은 메모리를 참조하고 오버랩되어 충돌이 발생합니다.
87 |
88 | 
89 |
90 | 이 충돌을 해결하는 한가지 방법은 `stepSize` 의 복사본을 명확하게 지정하는 것입니다:
91 |
92 | ```swift
93 | // Make an explicit copy.
94 | var copyOfStepSize = stepSize
95 | increment(©OfStepSize)
96 |
97 | // Update the original.
98 | stepSize = copyOfStepSize
99 | // stepSize is now 2
100 | ```
101 |
102 | `increment(_:)` 호출 전에 `stepSize` 의 복사본을 만들 때 `copyOfStepSize` 의 값이 현재 수만큼 증가된다는 것은 명확합니다. 읽기 접근은 쓰기 접근이 시작되기 전에 끝나므로 충돌이 일어나지 않습니다.
103 |
104 | in-out 파라미터에 대한 장기 쓰기 접근의 또 다른 결과는 같은 함수의 여러개의 in-out 파라미터에 대해 인수로 단일 변수를 전달하면 충돌이 발생한다는 것입니다. 예를 들어:
105 |
106 | ```swift
107 | func balance(_ x: inout Int, _ y: inout Int) {
108 | let sum = x + y
109 | x = sum / 2
110 | y = sum - x
111 | }
112 | var playerOneScore = 42
113 | var playerTwoScore = 30
114 | balance(&playerOneScore, &playerTwoScore) // OK
115 | balance(&playerOneScore, &playerOneScore)
116 | // Error: conflicting accesses to playerOneScore
117 | ```
118 |
119 | 위의 `balance(_:_:)` 함수는 총 값을 균등하게 나누기 위해 두 파라미터를 수정합니다. `playerOneScore` 와 `playerTwoScore` 를 인수로 사용하여 호출하면 두 쓰기 접근은 동시에 오버랩 되지만 메모리의 다른 위치를 접근하므로 충돌이 발생하지 않습니다. 반대로 두 파라미터 모두에 대해 값으로 `playerOneScore` 를 전달하면 동시에 메모리의 같은 위치를 두 쓰기 접근이 수행되므로 충돌이 일어납니다.
120 |
121 | > Note
122 | > 연산자는 함수이므로 in-out 파라미터에 장기 접근을 할 수도 있습니다. 예를 들어 `balance(_:_:)` 가 `<^>`라는 연산자 함수라면 `playerOneScore <^> playerOneScore` 를 작성하면 `balance(&playerOneScore, &playerOneScore)` 와 동일한 충돌이 발생합니다.
123 |
124 | ## 메서드에서 self에 충돌 접근 \(Conflicting Access to self in Methods\)
125 |
126 | 구조체의 변경 메서드는 메서드 호출 동안 `self` 에 대한 쓰기 접근을 가집니다. 예를 들어 각 플레이어는 데미지를 입으면 줄어드는 체력량과 특수 능력을 사용하면 줄어드는 에너지량을 가지는 게임이 있다고 생각해 봅시다.
127 |
128 | ```swift
129 | struct Player {
130 | var name: String
131 | var health: Int
132 | var energy: Int
133 |
134 | static let maxHealth = 10
135 | mutating func restoreHealth() {
136 | health = Player.maxHealth
137 | }
138 | }
139 | ```
140 |
141 | 위의 `restoreHealth()` 메서드에서 `self` 에 쓰기 접근은 메서드의 처음에서 시작하고 메서드가 반환될 때까지 유지됩니다. 이 경우에 `restoreHealth()` 내부에 `Player` 인스턴스의 프로퍼티에 중복 접근하는 다른 코드는 없습니다. 아래의 `shareHealth(with:)` 메서드는 in-out 파라미터로 다른 `Player` 인스턴스를 가지고 있으며 중복 접근에 대한 가능성을 만듭니다.
142 |
143 | ```swift
144 | extension Player {
145 | mutating func shareHealth(with teammate: inout Player) {
146 | balance(&teammate.health, &health)
147 | }
148 | }
149 |
150 | var oscar = Player(name: "Oscar", health: 10, energy: 10)
151 | var maria = Player(name: "Maria", health: 5, energy: 10)
152 | oscar.shareHealth(with: &maria) // OK
153 | ```
154 |
155 | 위의 예제에서 Maria 플레이어와 함께 체력을 공유하기 위해 Oscar 플레이어에 대한 `shareHealth(with:)` 메서드 호출은 중복을 야기 시키지 않습니다. `oscar` 는 변경 함수에서 `self` 의 값이기 때문에 `oscar` 에 대한 쓰기 접근이 있고 `maria` 는 in-out 파라미터로 전달되기 때문에 `maria` 에 대한 쓰기 접근이 있습니다. 아래 그림과 같이 메모리의 다른 위치를 접근합니다. 두 쓰기 접근이 동시에 오버랩 되지만 충돌이 일어나지 않습니다.
156 |
157 | 
158 |
159 | 그러나 `shareHealth(with:)` 의 인수로 `oscar` 를 전달하면 충돌이 일어납니다:
160 |
161 | ```swift
162 | oscar.shareHealth(with: &oscar)
163 | // Error: conflicting accesses to oscar
164 | ```
165 |
166 | 변경 메서드는 `self` 에 대한 쓰기 접근이 필요하고 in-out 파라미터는 `teammate` 에 쓰기 접근이 필요합니다. 메서드 내에서 `self` 와 `teammate` 모두는 아래 그림과 같이 메모리의 같은 위치를 참조합니다. 두 쓰기 접근이 같은 메모리를 참조하고 오버랩 되므로 충돌이 일어납니다.
167 |
168 | 
169 |
170 | ## 프로퍼티에서 충돌 접근 \(Conflicting Access to Properties\)
171 |
172 | 구조체, 튜플, 그리고 열거형과 같은 타입은 구조체의 프로퍼티 또는 튜플의 요소와 같은 개별 구성값으로 구성됩니다. 이것은 값 타입이기 때문에 값의 일부분을 변경하면 전체 값이 변경됩니다. 이것은 프로퍼티 중 하나에 읽기 또는 쓰기 접근은 전체 값에 읽기 또는 쓰기 접근을 요구합니다. 예를 들어 튜플의 요소에 쓰기 접근이 겹치면 충돌이 일어납니다:
173 |
174 | ```swift
175 | var playerInformation = (health: 10, energy: 20)
176 | balance(&playerInformation.health, &playerInformation.energy)
177 | // Error: conflicting access to properties of playerInformation
178 | ```
179 |
180 | 위의 예제에서 튜플의 요소에서 `balance(_:_:)` 를 호출하는 것은 `playerInformation` 에 중복 쓰기 접근이므로 충돌이 일어납니다. `playerInformation.health` 와 `playerInformation.energy` 모두는 `balance(_:_:)` 함수를 호출하는 동안 쓰기 접근이 필요하다는 의미의 in-out 파라미터로 전달됩니다. 이 경우 모두 튜플 요소에 쓰기 접근은 모든 튜플에 쓰기 접근을 요구합니다. 이것은 `playerInformation` 에 두 쓰기 접근이 오버랩 되므로 충돌이 일어납니다.
181 |
182 | 아래의 코드는 전역 변수에 저장된 구조체의 프로퍼티에 쓰기 접근이 중복될 때 동일한 에러가 발생하는 것을 보여줍니다.
183 |
184 | ```swift
185 | var holly = Player(name: "Holly", health: 10, energy: 10)
186 | balance(&holly.health, &holly.energy) // Error
187 | ```
188 |
189 | 실제로 대부분의 구조체의 프로퍼티에 접근하는 것은 안전하게 오버랩 될 수 있습니다. 예를 들어 위의 예제에서 변수 `holly` 는 전역 변수가 아닌 지역 변수로 변경되면 컴파일러는 구조체의 저장된 프로퍼티에 중복 접근이 안전하다고 증명할 수 있습니다:
190 |
191 | ```swift
192 | func someFunction() {
193 | var oscar = Player(name: "Oscar", health: 10, energy: 10)
194 | balance(&oscar.health, &oscar.energy) // OK
195 | }
196 | ```
197 |
198 | 위의 예제에서 Oscar의 체력과 에너지는 `balance(_:_:)` 에 2개의 in-out 파라미터로 전달됩니다. 컴파일러는 두 개의 저장된 프로퍼티가 어떤식으로도 상호작용 하지 않으므로 메모리 안정성이 안전하다고 증명할 수 있습니다.
199 |
200 | 구조체의 프로퍼티에 중복 접근에 대한 제한은 메모리 안정성을 위해 항상 필요한 것은 아닙니다. 메모리 안정성은 보장되지만 배타적 접근 \(exclusive access\)은 메모리 안정성 보다 더 엄격한 요구사항입니다. 이것은 일부 코드는 메모리에서 배타적 접근을 위반하더라도 메모리 안정성을 유지한다는 의미입니다. Swift는 컴파일러가 메모리에 배타적이지 않은 접근 \(nonexclusive access\)이 여전히 안전하다고 증명할 수 있으면 메모리 안전 코드를 허용합니다. 특히 아래의 조건이 적용되면 구조체의 프로퍼티에 중복 접근은 안전하다고 증명할 수 있습니다:
201 |
202 | * 계산된 프로퍼티 또는 클래스 프로퍼티가 아닌 인스턴스의 저장된 프로퍼티만 접근합니다.
203 | * 구조체는 전역 변수가 아닌 지역 변수의 값입니다.
204 | * 구조체는 클로저에 의해 캡쳐되지 않거나 nonescaping 클로저에 의해서만 캡처됩니다.
205 |
206 | 컴파일러가 접근이 안전하다는 것을 증명할 수 없으면 접근을 허용하지 않습니다.
207 |
208 |
--------------------------------------------------------------------------------
/language-guide-1/methods.md:
--------------------------------------------------------------------------------
1 | # 메서드 \(Methods\)
2 |
3 | 인스턴스 또는 타입의 부분인 함수를 정의하고 호출합니다.
4 |
5 | _메서드 \(Methods\)_ 는 특정 타입과 연관된 함수입니다. 클래스, 구조체, 그리고 열거형은 주어진 타입의 인스턴스 동작을 위한 특정 작업과 기능을 캡슐화하는 인스턴스 메서드를 정의할 수 있습니다. 클래스, 구조체, 그리고 열거형은 타입 자체와 연관된 타입 메서드를 정의할 수도 있습니다. 타입 메서드는 Objective-C에서 클래스 메서드와 유사합니다.
6 |
7 | Swift에서 구조체와 열거형에 메서드를 정의할 수 있다는 사실은 C와 Objective-C와의 가장 큰 차이점입니다. Objective-C에서 클래스는 메서드만 정의할 수 있는 유일한 타입입니다. Swift에서는 클래스, 구조체, 또는 열거형을 정의할 지 선택할 수 있으며 생성한 타입에 대한 메서드를 유연하게 정의할 수 있습니다.
8 |
9 | ## 인스턴스 메서드 \(Instance Methods\)
10 |
11 | _인스턴스 메서드 \(Instance methods\)_ 는 특정 클래스, 구조체, 또는 열거형의 인스턴스에 속하는 함수입니다. 인스턴스 프로퍼티에 접근하고 수정하는 방법을 제공하거나 인스턴스의 목적과 관련된 기능을 제공합니다. 인스턴스 메서드는 [함수 \(Functions\)](functions.md) 에서 설명한 대로 함수 구문과 완벽하게 동일합니다.
12 |
13 | 인스턴스 메서드는 속하는 타입의 중괄호 내에 작성합니다. 인스턴스 메서드는 다른 인스턴스 메서드와 타입의 프로퍼티에 암시적으로 접근할 수 있습니다. 인스턴스 메서드는 자신이 속한 타입의 특정 인스턴스에서만 호출될 수 있습니다. 기존 인스턴스 없이는 호출할 수 없습니다.
14 |
15 | 다음은 작업이 발생한 횟수를 계산하는데 사용할 수 있는 간단한 `Counter` 클래스 정의의 예입니다:
16 |
17 | ```swift
18 | class Counter {
19 | var count = 0
20 | func increment() {
21 | count += 1
22 | }
23 | func increment(by amount: Int) {
24 | count += amount
25 | }
26 | func reset() {
27 | count = 0
28 | }
29 | }
30 | ```
31 |
32 | `Counter` 클래스는 3개의 인스턴스 메서드를 정의합니다:
33 |
34 | * `increment()` 는 `1` 씩 카운터를 증가시킵니다.
35 | * `increment(by: Int)` 는 특정 정수 크기만큼 카운터를 증가시킵니다.
36 | * `reset()` 은 카운터를 0으로 재설정 합니다.
37 |
38 | `Counter` 클래스는 현재 카운터 값을 추적하는 `count` 프로퍼티 변수도 선언합니다.
39 |
40 | 프로퍼티와 동일하게 점 구문으로 인스턴스 메서드를 호출합니다:
41 |
42 | ```swift
43 | let counter = Counter()
44 | // the initial counter value is 0
45 | counter.increment()
46 | // the counter's value is now 1
47 | counter.increment(by: 5)
48 | // the counter's value is now 6
49 | counter.reset()
50 | // the counter's value is now 0
51 | ```
52 |
53 | 함수 파라미터는 [함수 인수 라벨과 파라미터 이름 \(Function Argument Labels and Parameter Names\)](functions.md#function-argument-labels-and-parameter-names) 에서 설명 했듯이 함수의 본문 내에서 사용하는 이름과 함수를 호출할 때 사용하는 인수 라벨 둘다 가질 수 있습니다. 메서드는 타입과 관련된 함수이므로 메서드 파라미터도 동일하게 적용됩니다.
54 |
55 | ### self 프로퍼티 \(The self Property\)
56 |
57 | 타입의 모든 인스턴스는 인스턴스 자체와 정확하게 일치하는 `self` 라는 암시적 프로퍼티를 가지고 있습니다. 자체 인스턴스 메서드 내에서 현재 인스턴스를 참조하기 위해 `self` 프로퍼티를 사용합니다.
58 |
59 | 위 예제에서 `increment()` 메서드는 아래와 같이 작성될 수 있습니다:
60 |
61 | ```swift
62 | func increment() {
63 | self.count += 1
64 | }
65 | ```
66 |
67 | 실제로 코드에서 `self` 를 꼭 작성할 필요가 없습니다. `self` 를 명시적으로 작성하지 않으면 Swift는 메서드 내에서 이미 알고 있는 프로퍼티 또는 메서드 이름을 사용할 때마다 현재 인스턴스의 프로퍼티 또는 메서드를 참조한다고 가정합니다. 이 가정은 `Counter` 에 3개의 인스턴스 메서드 내에서 `self.count` 가 아닌 `count` 를 사용하여 입증됩니다.
68 |
69 | 이 규칙의 주요 예외사항은 인스턴스 메서드에 파라미터 명이 그 인스턴스에 프로퍼티 명과 동일할 때 발생합니다. 이러한 경우 파라미터 명이 더 우선시 되고 프로퍼티를 참조하려면 더 규정된 방식으로 참조해야 합니다. 파라미터 명과 프로퍼티 명을 분리하기 위해 `self` 프로퍼티를 사용합니다.
70 |
71 | 여기서 `self` 는 `x` 라는 메서드 파라미터와 `x` 라고 하는 인스턴스 프로퍼티를 명확하게 합니다:
72 |
73 | ```swift
74 | struct Point {
75 | var x = 0.0, y = 0.0
76 | func isToTheRightOf(x: Double) -> Bool {
77 | return self.x > x
78 | }
79 | }
80 | let somePoint = Point(x: 4.0, y: 5.0)
81 | if somePoint.isToTheRightOf(x: 1.0) {
82 | print("This point is to the right of the line where x == 1.0")
83 | }
84 | // Prints "This point is to the right of the line where x == 1.0"
85 | ```
86 |
87 | `self` 접두사가 없으면 Swift는 `x` 의 2가지 사용이 모두 `x` 라는 메서드 파라미터를 참조한다고 가정합니다.
88 |
89 | ### 인스턴스 메서드 내에서 값 타입 수정 \(Modifying Value Types from Within Instance Methods\)
90 |
91 | 구조체와 열거형은 _값 타입_ 입니다. 기본적으로 값 타입의 프로퍼티는 인스턴스 메서드 내에서 수정될 수 없습니다.
92 |
93 | 그러나 특정 메서드 내에서 구조체나 열거형의 프로퍼티 수정이 필요하다면 해당 메서드에 대한 동작을 _변경_ 하도록 선택할 수 있습니다. 그러면 이 메서드는 메서드 내에서 프로퍼티를 변경할 수 있고 메서드가 끝나면 기존 구조체에 변경사항이 작성됩니다. 이 메서드는 암시적 `self` 프로퍼티에 새로운 인스턴스를 할당하고 새로운 인스턴스는 메서드가 종료되면 기존에 존재하던 인스턴스를 대체하게 됩니다.
94 |
95 | 해당 메서드는 `func` 키워드 전에 `mutating` 키워드를 위치 시켜 이 동작을 선택할 수 있습니다:
96 |
97 | ```swift
98 | struct Point {
99 | var x = 0.0, y = 0.0
100 | mutating func moveBy(x deltaX: Double, y deltaY: Double) {
101 | x += deltaX
102 | y += deltaY
103 | }
104 | }
105 | var somePoint = Point(x: 1.0, y: 1.0)
106 | somePoint.moveBy(x: 2.0, y: 3.0)
107 | print("The point is now at (\(somePoint.x), \(somePoint.y))")
108 | // Prints "The point is now at (3.0, 4.0)"
109 | ```
110 |
111 | 위의 `Point` 구조체는 포함한 양만큼 `Point` 인스턴스를 이동시키는 변경가능한 `moveBy(x:y:)` 메서드를 정의합니다. 새로운 위치를 반환하는 대신에 이 메서드는 실제로 호출된 위치를 수정합니다. `mutating` 키워드는 프로퍼티를 수정할 수 있도록 정의에 추가됩니다.
112 |
113 | [상수 구조체 인스턴스의 저장된 프로퍼티 \(Stored Properties of Constant Structure Instances\)](properties.md#stored-properties-of-constant-structure-instances) 에서 설명했듯이 프로퍼티가 프로퍼티 변수이더라도 변경할 수 없기 때문에 구조체 타입의 상수에 대해 변경 메서드를 호출할 수 없습니다:
114 |
115 | ```swift
116 | let fixedPoint = Point(x: 3.0, y: 3.0)
117 | fixedPoint.moveBy(x: 2.0, y: 3.0)
118 | // this will report an error
119 | ```
120 |
121 | ### 변경 메서드 내에서 self 할당 \(Assigning to self Within a Mutating Method\)
122 |
123 | 변경 메서드 \(Mutating methods\)는 암시적 `self` 프로퍼티를 완전히 새로운 인스턴스로 할당할 수 있습니다. 위에서 본 `Point` 예제는 대신 다음과 같은 방식으로 작성되었을 수도 있습니다:
124 |
125 | ```swift
126 | struct Point {
127 | var x = 0.0, y = 0.0
128 | mutating func moveBy(x deltaX: Double, y deltaY: Double) {
129 | self = Point(x: x + deltaX, y: y + deltaY)
130 | }
131 | }
132 | ```
133 |
134 | 이 버전의 변경가능한 `moveBy(x:y:)` 메서드는 `x` 와 `y` 값이 대상 위치로 설정된 새로운 구조체를 생성합니다. 이 대체 버전의 메서드를 호출한 최종 결과는 이전 버전의 호출 결과와 동일합니다.
135 |
136 | 열거형의 변경 메서드는 동일한 열거형에서 다른 케이스로 암시적으로 `self` 파라미터를 설정할 수 있습니다:
137 |
138 | ```swift
139 | enum TriStateSwitch {
140 | case off, low, high
141 | mutating func next() {
142 | switch self {
143 | case .off:
144 | self = .low
145 | case .low:
146 | self = .high
147 | case .high:
148 | self = .off
149 | }
150 | }
151 | }
152 | var ovenLight = TriStateSwitch.low
153 | ovenLight.next()
154 | // ovenLight is now equal to .high
155 | ovenLight.next()
156 | // ovenLight is now equal to .off
157 | ```
158 |
159 | 이 예제는 3개의 상태를 나타내는 스위치를 열거형으로 정의합니다. 이 스위치는 `next()` 메서드가 호출될 때마다 3개의 전원 상태 \(`off`, `low`, `high`\)를 순환합니다.
160 |
161 | ## 타입 메서드 \(Type Methods\)
162 |
163 | 위에 설명한 인스턴스 메서드는 특정 타입의 인스턴스에서 호출하는 메서드 입니다. 타입 자체에서 호출되는 메서드도 정의할 수 있습니다. 이런 종류의 메서드를 _타입 메서드 \(type methods\)_ 라고 합니다. 메서드의 `func` 키워드 전에 `static` 키워드를 작성하여 타입 메서드를 나타냅니다. 클래스는 대신 `class` 키워드를 사용하여 하위 클래스가 해당 메서드의 상위 클래스 구현을 재정의 할 수 있습니다.
164 |
165 | > Note
166 | > Objective-C에서는 Objective-C 클래스에 대해서만 타입 레벨 메서드 \(type-level methods\)를 정의할 수 있습니다. Swift에서는 모든 클래스, 구조체, 그리고 열거형에 대해서 타입 레벨 메서드를 정의할 수 있습니다. 각 타입 메서드는 지원하는 타입으로 명시적으로 범위가 지정됩니다.
167 |
168 | 타입 메서드는 인스턴스 메서드처럼 점 구문으로 호출됩니다. 그러나 해당 타입의 인스턴스가 아닌 타입으로 타입 메서드를 호출합니다. `SomeClass` 라는 클래스에서 타입 메서드를 호출하는 방법은 다음과 같습니다:
169 |
170 | ```swift
171 | class SomeClass {
172 | class func someTypeMethod() {
173 | // type method implementation goes here
174 | }
175 | }
176 | SomeClass.someTypeMethod()
177 | ```
178 |
179 | 타입 메서드의 본문 내에서 암시적 `self` 프로퍼티는 타입의 인스턴스가 아닌 타입 자체를 참조합니다. 인스턴스 프로퍼티와 인스턴스 메서드 파라미터에서와 같이 `self` 를 타입 프로퍼티와 타입 메서드 파라미터를 명확하게 하기위해 사용할 수 있다는 의미입니다.
180 |
181 | 일반적으로 타입 메서드의 본문 내에서 사용하는 정규화되지 않은 메서드와 프로퍼티 이름은 다른 타입 레벨 메서드와 프로퍼티를 참조합니다. 타입 메서드는 타입 이름을 접두어로 필요치 않고 다른 메서드의 이름으로 다른 타입 메서드를 호출할 수 있습니다. 유사하게 구조체와 열거형에서 타입 메서드는 타입 이름 접두어 없이 타입 프로퍼티의 이름을 사용하여 타입 프로퍼티에 접근할 수 있습니다.
182 |
183 | 아래 예제는 게임의 다른 레벨 또는 스테이지를 통해 사용자의 진행상황을 추적하는 `LevelTracker` 라는 구조체를 정의합니다. 이것은 1인용 게임이지만 단일 디바이스에서 여러명의 플레이어를 위한 정보를 저장할 수 있습니다.
184 |
185 | 첫번째 레벨을 제외한 게임의 모든 레벨은 게임을 처음 플레이할 때 잠겨있습니다. 플레이어가 레벨을 끝낼 때마다 디바이스에 모든 플레이어가 플레이 할 수 있도록 레벨이 풀립니다. `LevelTracker` 구조체는 게임의 레벨이 풀리는 것을 추적하기 위해 타입 프로퍼티와 메서드를 사용합니다. 각 플레이어의 현재 레벨도 추적합니다.
186 |
187 | ```swift
188 | struct LevelTracker {
189 | static var highestUnlockedLevel = 1
190 | var currentLevel = 1
191 |
192 | static func unlock(_ level: Int) {
193 | if level > highestUnlockedLevel { highestUnlockedLevel = level }
194 | }
195 |
196 | static func isUnlocked(_ level: Int) -> Bool {
197 | return level <= highestUnlockedLevel
198 | }
199 |
200 | @discardableResult
201 | mutating func advance(to level: Int) -> Bool {
202 | if LevelTracker.isUnlocked(level) {
203 | currentLevel = level
204 | return true
205 | } else {
206 | return false
207 | }
208 | }
209 | }
210 | ```
211 |
212 | `LevelTracker` 구조체는 모든 플레이어가 푼 가장 높은 레벨을 추적합니다. 이 값은 `highestUnlockedLevel` 이라는 타입 프로퍼티에 저장됩니다.
213 |
214 | `LevelTracker` 는 `highestUnlockedLevel` 프로퍼티와 함께 동작하는 2개의 타입 함수도 정의합니다. 첫번째 타입 함수는 `unlock(_:)` 이라 하며 새로운 레벨이 풀릴 때마다 `highestUnlockedLevel` 의 값을 업데이트 합니다. 두번째 타입 함수는 `isUnlocked(_:)` 이라 하며 편의 타입 함수이며 특정 레벨이 이미 풀려있다면 `true` 를 반환합니다 \(이 타입 메서드는 `LevelTracker.highestUnlockedLevel` 로 작성할 필요없이 `highestUnlockedLevel` 타입 프로퍼티를 접근할 수 있습니다\).
215 |
216 | 타입 프로퍼티와 타입 메서드 외에도 `LevelTracker` 는 게임을 통해 각 플레이어의 진행사항을 추적합니다. 플레이어가 현재 플레이 중인 레벨을 추적하는 `currentLevel` 이라는 인스턴스 프로퍼티를 사용합니다.
217 |
218 | `currentLevel` 프로퍼티 관리를 돕기위해 `LevelTracker` 는 `advance(to:)` 라는 인스턴스 메서드를 정의합니다. `currentLevel` 업데이트 전에 이 메서드는 요청된 새 레벨이 이미 풀렸는지 판단합니다. `advance(to:)` 메서드는 `currentLevel` 을 설정가능한지 아닌지를 나타내기 위해 부울값으로 반환합니다. `advance(to:)` 메서드를 호출하여 반환값을 무시하는 코드가 실수가 아니기 때문에 이 함수는 `@discardableResult` 속성으로 표시됩니다. 더 자세한 내용은 [속성 \(Attributes\)](../language-reference/attributes.md) 을 참고 바랍니다.
219 |
220 | `LevelTracker` 구조체는 아래에서 봤듯이 각 플레이어의 진행상태를 추적하고 업데이트 하기 위해 `Player` 클래스와 함께 사용됩니다:
221 |
222 | ```swift
223 | class Player {
224 | var tracker = LevelTracker()
225 | let playerName: String
226 | func complete(level: Int) {
227 | LevelTracker.unlock(level + 1)
228 | tracker.advance(to: level + 1)
229 | }
230 | init(name: String) {
231 | playerName = name
232 | }
233 | }
234 | ```
235 |
236 | `Player` 클래스는 플레이어의 진행상태를 추적하기 위해 새로운 `LevelTracker` 의 인스턴스를 생성합니다. 플레이어가 특정 레벨을 완료했는지 판단하는 `complete(level:)` 이라는 메서드도 제공합니다. 이 메서드는 모든 플레이어에게 다음 레벨을 풀고 다음 레벨로 이동하기 위해 플레이어의 진행상태를 업데이트 합니다 \(이전 라인에서 `LevelTracker.unlock(_:)` 을 호출하여 해당 레벨을 풀기 때문에 `advance(to:)` 의 부울 반환 값은 무시됩니다\).
237 |
238 | 새로운 플레이어를 위한 `Player` 클래스의 인스턴스를 생성할 수 있고 플레이어가 레벨1을 완료하면 어떤 일이 생기는지 알 수 있습니다:
239 |
240 | ```swift
241 | var player = Player(name: "Argyrios")
242 | player.complete(level: 1)
243 | print("highest unlocked level is now \(LevelTracker.highestUnlockedLevel)")
244 | // Prints "highest unlocked level is now 2"
245 | ```
246 |
247 | 게임에서 아직 풀리지 않은 레벨로 이동을 하려는 2번째 플레이어를 생성하면 플레이어의 현재 레벨을 실패로 설정합니다:
248 |
249 | ```swift
250 | player = Player(name: "Beto")
251 | if player.tracker.advance(to: 6) {
252 | print("player is now on level 6")
253 | } else {
254 | print("level 6 has not yet been unlocked")
255 | }
256 | // Prints "level 6 has not yet been unlocked"
257 | ```
258 |
259 |
--------------------------------------------------------------------------------
/language-guide-1/nested-types.md:
--------------------------------------------------------------------------------
1 | # 중첩된 타입 \(Nested Types\)
2 |
3 | 타입의 범위안에 타입을 정의합니다.
4 |
5 | 열거형은 특정 클래스 또는 구조체의 기능을 지원하기 위해 생성됩니다.
6 | 유사하게 더 복잡한 타입의 컨텍스트 내에서 사용하기 위해
7 | 유틸리티 구조체와 일반적으로 특정 타입과 함께 사용되는 프로토콜을 정의하는 것이 편리할 수 있습니다.
8 | 이를 위해 Swift는 _중첩된 타입 \(nested types\)_ 을
9 | 정의할 수 있으며 지원하는 타입의 정의 내에서 열거형, 구조체,
10 | 그리고 프로토콜과 같은 타입을 중첩할 수 있습니다.
11 |
12 | 다른 타입 내에서 타입을 중첩하려면 지원하는 타입의 외부 중괄호 내에 정의를 작성해야 합니다. 타입은 필요한만큼의 수준으로 중첩될 수 있습니다.
13 |
14 | ## 중첩된 타입의 동작 \(Nested Types in Action\)
15 |
16 | 아래의 예제는 블랙잭 게임에서 사용되는 게임 카드를 모델링하는 `BlackjackCard` 라는 구조체를 정의합니다. `BlackjackCard` 구조체는 `Suit` 와 `Rank` 라는 2개의 중첩된 열거형을 포함합니다.
17 |
18 | 블랙잭에서 에이스 카드의 값은 1 또는 11 입니다. 이러한 특징은 `Rank` 열거형 내에 중첩된 `Values` 라는 구조체로 나타냅니다:
19 |
20 | ```swift
21 | struct BlackjackCard {
22 |
23 | // nested Suit enumeration
24 | enum Suit: Character {
25 | case spades = "♠", hearts = "♡", diamonds = "♢", clubs = "♣"
26 | }
27 |
28 | // nested Rank enumeration
29 | enum Rank: Int {
30 | case two = 2, three, four, five, six, seven, eight, nine, ten
31 | case jack, queen, king, ace
32 | struct Values {
33 | let first: Int, second: Int?
34 | }
35 | var values: Values {
36 | switch self {
37 | case .ace:
38 | return Values(first: 1, second: 11)
39 | case .jack, .queen, .king:
40 | return Values(first: 10, second: nil)
41 | default:
42 | return Values(first: self.rawValue, second: nil)
43 | }
44 | }
45 | }
46 |
47 | // BlackjackCard properties and methods
48 | let rank: Rank, suit: Suit
49 | var description: String {
50 | var output = "suit is \(suit.rawValue),"
51 | output += " value is \(rank.values.first)"
52 | if let second = rank.values.second {
53 | output += " or \(second)"
54 | }
55 | return output
56 | }
57 | }
58 | ```
59 |
60 | `Suit` 열거형은 기호를 나타내는 원시 `Character` 값과 함께 4개의 일반적인 카드 모양을 나타냅니다.
61 |
62 | `Rank` 열거형은 카드값을 나타내는 원시 `Int` 값과 함께 가능한 13개의 카드 순위를 나타냅니다 \(이 원시 `Int` 값은 Jack, Queen, King, 그리고 Ace 카드에는 사용되지 않습니다\).
63 |
64 | 위에서 말했듯이 `Rank` 열거형은 `Values` 라는 자신의 중첩된 구조체를 더 정의합니다. 이 구조체는 대부분의 카드는 하나의 값을 가지지만 에이스 카드는 2개의 값을 가지는 사실을 캡슐화 합니다. `Values` 구조체는 다음과 같이 2개의 프로퍼티를 정의합니다:
65 |
66 | * `Int` 타입의 `first`
67 | * `Int?` 또는 "옵셔널 `Int`" 타입의 `second`
68 |
69 | `Rank` 는 `Values` 구조체의 인스턴스를 반환하는 `values` 라는 계산된 프로퍼티도 정의합니다. 이 계산된 프로퍼티는 카드의 순위를 고려하고 그 순위를 기반으로 적절한 값으로 새로운 `Values` 인스턴스를 초기화 합니다. `jack`, `queen`, `king`, 그리고 `ace` 에 대한 특별한 값을 사용합니다. 숫자 카드에 대해서는 순위의 원시 `Int` 값을 사용합니다.
70 |
71 | `BlackjackCard` 구조체 자체는 `rank` 와 `suit` 의 2개의 프로퍼티를 가지고 있습니다. 이름과 카드의 값의 설명을 만들기 위해 `rank` 와 `suit` 에 저장된 값을 사용하는 `description` 이라는 계산된 프로퍼티도 정의합니다. `description` 프로퍼티는 화면에 표시하기 위해 두번째 값이 있는지 확인하고 있으면 두번째 값에 대해 상세 설명을 추가합니다.
72 |
73 | `BlackjackCard` 는 사용자 지정 초기화 구문이 없는 구조체이기 때문에 [구조체 타입에 대한 멤버별 초기화 구문 \(Memberwise Initializers for Structure Types\)](initialization.md#memberwise-initializers-for-structure-types) 에서 설명 했듯이 암시적 멤버별 초기화 구문을 가지고 있습니다. `theAceOfSpades` 라는 새로운 상수를 초기화 하기 위해 초기화 구문을 사용할 수 있습니다:
74 |
75 | ```swift
76 | let theAceOfSpades = BlackjackCard(rank: .ace, suit: .spades)
77 | print("theAceOfSpades: \(theAceOfSpades.description)")
78 | // Prints "theAceOfSpades: suit is ♠, value is 1 or 11"
79 | ```
80 |
81 | `Rank` 와 `Suit` 은 `BlackjackCard` 내에 중첩되어 있지만 타입은 컨텍스트로 부터 유추될 수 있기 때문에 이 인스턴스의 초기화는 케이스 이름 \(`.ace` 와 `.spades`\) 만으로 열거형 케이스를 참조할 수 있습니다. 위의 예제에서 `description` 프로퍼티는 스페이드의 에이스는 `1` 또는 `11` 의 값을 가지고 있다고 올바르게 보여줍니다.
82 |
83 | ## 중첩된 타입 참조 \(Referring to Nested Types\)
84 |
85 | 정의 컨텍스트 외부에서 중첩된 타입을 사용하기 위해 해당 이름에 중첩된 타입의 이름을 접두사로 붙입니다:
86 |
87 | ```swift
88 | let heartsSymbol = BlackjackCard.Suit.hearts.rawValue
89 | // heartsSymbol is "♡"
90 | ```
91 |
92 | 위의 예제에서 `Suit`, `Rank` 그리고 `Values` 의 이름은 정의된 컨텍스트에 따라 자연스럽게 규정되기 때문에 의도적으로 짧게 유지할 수 있습니다.
93 |
94 |
--------------------------------------------------------------------------------
/language-guide-1/opaque-types.md:
--------------------------------------------------------------------------------
1 | # 불투명한 타입과 박스형 프로토콜 타입 \(Opaque and Boxed Protocol Types\)
2 |
3 | 값의 타입에 대한 자세한 정보를 숨깁니다.
4 |
5 | Swift 는 값의 타입에 대한 자세한 내용을 숨기기위한 두가지 방법을 제공합니다: 불투명한 타입 (opaque type) 과 박스형 프로토콜 타입 (boxed protocol type). 반환값의 기본 타입이 비공개로 유지될 수 있으므로 모듈과 모듈을 호출하는 코드 사이의 경계에서 타입 정보를 숨기는 것이 유용합니다.
6 |
7 | 불투명한 타입을 반환하는 함수 또는 메서드는 반환되는 값의 타입 정보를 숨깁니다. 함수의 반환 타입으로 구체적인 타입을 제공하는 대신에 지원하는 프로토콜에서 설명됩니다. 불투명한 타입은 타입 식별을 유지합니다 — 컴파일러는 타입 정보에 접근할 수 있지만 모듈의 클라이언트는 그럴 수 없습니다.
8 |
9 | 박스형 프로토콜 타입은 주어진 프로토콜을 준수하는 타입의 인스턴스를 저장할 수 있습니다. 박스형 프로토콜 타입은 타입 식별을 유지하지 않습니다 — 값의 타입은 런타임까지 알 수 없으며 다른 값이 저장됨에 따라 변경될 수 있습니다.
10 |
11 | ## 불투명한 타입이 해결하는 문제 \(The Problem That Opaque Types Solve\)
12 |
13 | 예를 들어 ASCII 그림 모양을 그리는 모듈을 작성한다고 가정합시다. ASCII 그림 모양의 기본 특성은 `Shape` 프로토콜에 대한 요구사항으로 사용될 수 있는 모양의 문자열 표현을 반환하는 `draw()` 함수 입니다:
14 |
15 | ```swift
16 | protocol Shape {
17 | func draw() -> String
18 | }
19 |
20 | struct Triangle: Shape {
21 | var size: Int
22 | func draw() -> String {
23 | var result: [String] = []
24 | for length in 1...size {
25 | result.append(String(repeating: "*", count: length))
26 | }
27 | return result.joined(separator: "\n")
28 | }
29 | }
30 | let smallTriangle = Triangle(size: 3)
31 | print(smallTriangle.draw())
32 | // *
33 | // **
34 | // ***
35 | ```
36 |
37 | 아래 코드와 같이 제너릭을 사용하여 모양을 수직으로 뒤집는 것과 같은 작업을 구현할 수 있습니다. 그러나 이 접근 방식에는 중요한 제한이 있습니다: 뒤집힌 결과는 이를 생성하는데 정확한 제너릭 타입을 노출합니다.
38 |
39 | ```swift
40 | struct FlippedShape: Shape {
41 | var shape: T
42 | func draw() -> String {
43 | let lines = shape.draw().split(separator: "\n")
44 | return lines.reversed().joined(separator: "\n")
45 | }
46 | }
47 | let flippedTriangle = FlippedShape(shape: smallTriangle)
48 | print(flippedTriangle.draw())
49 | // ***
50 | // **
51 | // *
52 | ```
53 |
54 | 아래의 코드와 같이 두개의 모양을 수직으로 결합하는
55 | `JoinedShape` 구조체를 정의하는
56 | 이 접근방식은 뒤집힌 삼각형을 다른 삼각형과 결합하는
57 | `JoinedShape>` 과 같은 타입을 생성합니다.
58 |
59 | ```swift
60 | struct JoinedShape: Shape {
61 | var top: T
62 | var bottom: U
63 | func draw() -> String {
64 | return top.draw() + "\n" + bottom.draw()
65 | }
66 | }
67 | let joinedTriangles = JoinedShape(top: smallTriangle, bottom: flippedTriangle)
68 | print(joinedTriangles.draw())
69 | // *
70 | // **
71 | // ***
72 | // ***
73 | // **
74 | // *
75 | ```
76 |
77 | 모양 생성에 대한 자세한 내용을 표출하면 전체 반환 타입을 명시해야 하므로 ASCII 그림 모듈의 공개 인터페이스에 포함되지 않은 타입이 유출될 수 있습니다. 모듈내에 코드는 다양한 방법으로 같은 모양을 구축할 수 있으며 모양을 사용하는 모듈 바깥에서의 다른 코드는 변환 리스트에 대한 세부 구현 정보를 고려할 필요가 없습니다. `JoinedShape` 와 `FlippedShape` 와 같은 래퍼 타입은 모듈의 사용자에게 중요하지 않으며 표시되지 않아야 합니다. 모듈의 공개 인터페이스는 모양을 결합하고 뒤집는 것과 같은 작업으로 구성되며 이러한 작업은 다른 `Shape` 값을 반환합니다.
78 |
79 | ## 불투명한 타입 반환 \(Returning an Opaque Type\)
80 |
81 | 불투명한 타입은 제너릭 타입과 반대라고 생각할 수 있습니다. 제너릭 타입을 사용하면 함수를 호출하는 코드에서 해당 함수의 파라미터에 대한 타입을 선택하고 함수 구현에서 추상화된 방식으로 값을 반환할 수 있습니다. 예를 들어 다음 코드의 함수는 호출자에 따라 달라지는 타입을 반환합니다:
82 |
83 | ```swift
84 | func max(_ x: T, _ y: T) -> T where T: Comparable { ... }
85 | ```
86 |
87 | `max(_:_:)` 호출하는 코드는 `x` 와 `y` 에 대한 값을 선택하고 이 값의 타입에 따라 `T` 의 구체적인 타입을 결정합니다. 코드 호출은 `Comparable` 프로토콜을 준수하는 모든 타입을 사용할 수 있습니다. 함수 내부의 코드는 일반적인 방식으로 작성되므로 호출자가 제공하는 타입이 무엇이든 처리할 수 있습니다. `max(_:_:)` 의 구현은 모든 `Comparable` 타입이 공유하는 기능만 사용합니다.
88 |
89 | 불투명한 반환 타입을 사용하는 함수의 경우 이러한 역할이 반전됩니다. 불투명한 타입을 사용하면 함수 구현에서 함수를 호출하는 코드에서 추상화 된 방식으로 반환되는 값의 타입을 선택할 수 있습니다. 예를 들어 다음의 예제에서 함수는 모양의 기본 타입을 노출하지 않고 사다리꼴을 반환합니다.
90 |
91 | ```swift
92 | struct Square: Shape {
93 | var size: Int
94 | func draw() -> String {
95 | let line = String(repeating: "*", count: size)
96 | let result = Array(repeating: line, count: size)
97 | return result.joined(separator: "\n")
98 | }
99 | }
100 |
101 | func makeTrapezoid() -> some Shape {
102 | let top = Triangle(size: 2)
103 | let middle = Square(size: 2)
104 | let bottom = FlippedShape(shape: top)
105 | let trapezoid = JoinedShape(
106 | top: top,
107 | bottom: JoinedShape(top: middle, bottom: bottom)
108 | )
109 | return trapezoid
110 | }
111 | let trapezoid = makeTrapezoid()
112 | print(trapezoid.draw())
113 | // *
114 | // **
115 | // **
116 | // **
117 | // **
118 | // *
119 | ```
120 |
121 | 이 예제에서 `makeTrapezoid()` 함수는 `some Shape` 로 반환 타입을 선언하고 그 결과 이 함수는 특정 구체적인 타입을 지정하지 않고 `Shape` 프로토콜을 준수하는 특정 타입의 값을 반환합니다. 이러한 방식으로 `makeTrapezoid()` 를 작성하면 공용 인터페이스의 부분으로 만들어지는 모양을 타입으로 지정하지 않고도 반환하는 값이 모양 인 공용 인터페이스의 기본 측면을 표현할 수 있습니다. 이 구현은 2개의 삼각형과 하나의 사각형을 사용하지만 이 함수는 반환 타입을 변경하지 않고 다양한 방법으로 사다리꼴을 그리기 위해 다시 작성할 수 있습니다.
122 |
123 | 이 예제는 불투명한 반환 타입은 제너릭 타입의 반대와 같은 방식을 강조합니다. `makeTrapezoid()` 안에 코드는 호출하는 코드가 제너릭 함수처럼 해당 타입이 `Shape` 프로토콜을 준수하는 한 필요한 모든 타입을 반환할 수 있습니다. 함수를 호출하는 코드는 `makeTrapezoid()` 에 의해 반환된 모든 `Shape` 값과 함께 동작할 수 있도록 제너릭 함수의 구현과 같이 일반적인 방식으로 작성되어야 합니다.
124 |
125 | 불투명한 반환 타입은 제너릭과 결합할 수도 있습니다. 다음 코드의 함수는 모두 `Shape` 프로토콜을 준수하는 일부 타입의 값을 반환합니다.
126 |
127 | ```swift
128 | func flip(_ shape: T) -> some Shape {
129 | return FlippedShape(shape: shape)
130 | }
131 | func join(_ top: T, _ bottom: U) -> some Shape {
132 | JoinedShape(top: top, bottom: bottom)
133 | }
134 |
135 | let opaqueJoinedTriangles = join(smallTriangle, flip(smallTriangle))
136 | print(opaqueJoinedTriangles.draw())
137 | // *
138 | // **
139 | // ***
140 | // ***
141 | // **
142 | // *
143 | ```
144 |
145 | 이 예제의 `opaqueJoinedTriangles` 의 값은 이 챕터의 이전 [불투명한 타입이 해결하는 문제 \(The Problem That Opaque Types Solve\)](opaque-types.md#the-problem-that-opaque-types-solve) 섹션에 제너릭 예제에서 `joinedTriangles` 와 동일합니다. 그러나 이 예제의 값과 달리 `flip(_:)` 과 `join(_:_:)` 은 불투명한 반환 타입으로 반환하는 제너릭 모양 연산자 인 기본 타입을 래핑하여 해당 타입이 표시되지 않도록 합니다. 두 함수는 의존하는 타입이 제너릭이고 함수에 대한 타입 파라미터가 `FlippedShape` 와 `JoinedShape` 에 필요한 타입 정보를 전달하기 때문에 모두 제너릭입니다.
146 |
147 | 불투명한 반환 타입을 가진 함수가 여러 위치에서 반환하는 경우 가능한 모든 반환 값은 동일한 타입을 가져야 합니다. 제너릭 함수의 경우 해당 반환 타입은 함수의 제너릭 타입 파라미터로 사용할 수 있지만 여전히 단일 타입이어야 합니다. 예를 들어 다음은 사각형에 대한 특수 케이스를 포함하는 잘못된 버전의 모양 - 뒤집기 함수 입니다:
148 |
149 | ```swift
150 | func invalidFlip(_ shape: T) -> some Shape {
151 | if shape is Square {
152 | return shape // Error: return types don't match
153 | }
154 | return FlippedShape(shape: shape) // Error: return types don't match
155 | }
156 | ```
157 |
158 | 이 함수를 `Square` 와 함께 호출하면 `Square` 를 반환하고 그렇지 않으면 `FlippedShape` 를 반환합니다. 이것은 단일 타입의 값을 반환해야 한다는 요구사항을 위반하고 `invalidFlip(_:)` 코드를 유효하지 않게 만듭니다. `invalidFlip(_:)` 을 고치기 위한 한가지 방법은 사각형의 특수한 경우를 `FlippedShape` 의 구현으로 옮기는 것입니다. 이렇게 하면 이 함수는 항상 `FlippedShape` 값을 반환할 수 있습니다:
159 |
160 | ```swift
161 | struct FlippedShape: Shape {
162 | var shape: T
163 | func draw() -> String {
164 | if shape is Square {
165 | return shape.draw()
166 | }
167 | let lines = shape.draw().split(separator: "\n")
168 | return lines.reversed().joined(separator: "\n")
169 | }
170 | }
171 | ```
172 |
173 | 항상 단일 타입을 반환해야 한다고 해서 불투명 반환 타입에 제너릭 사용을 막지는 않습니다. 다음은 반환하는 값의 기본 타입에 타입 파라미터를 통합하는 함수의 예입니다:
174 |
175 | ```swift
176 | func `repeat`(shape: T, count: Int) -> some Collection {
177 | return Array(repeating: shape, count: count)
178 | }
179 | ```
180 |
181 | 이 경우에 반환값의 기본 타입은 `T` 에 따라 달라집니다: 전달되는 모양이 무엇이든 `repeat(shape:count:)` 는 해당 모양의 배열을 생성하고 반환합니다. 그럼에도 불구하고 반환값은 항상 동일한 기본 타입 인 `[T]` 를 가지므로 불투명한 반환 타입을 가진 함수는 단일 타입의 값만 가져야 한다는 요구사항을 따릅니다.
182 |
183 | ## 박스형 프로토콜 타입 (Boxed Protocol Types)
184 |
185 | 박스형 프로토콜 타입 (Boxed protocol type) 은 "프로토콜을 준수하는 _T_ 타입이 존재합니다." 라는 문구와 같이 _존재 타입 (existential type)_ 이라고도 불립니다. 프로토콜의 이름 앞에 `any` 를 적어 박스형 프로토콜 타입을 만듭니다. 예를 들면 다음과 같습니다:
186 |
187 | ```swift
188 | struct VerticalShapes: Shape {
189 | var shapes: [any Shape]
190 | func draw() -> String {
191 | return shapes.map { $0.draw() }.joined(separator: "\n\n")
192 | }
193 | }
194 |
195 |
196 | let largeTriangle = Triangle(size: 5)
197 | let largeSquare = Square(size: 5)
198 | let vertical = VerticalShapes(shapes: [largeTriangle, largeSquare])
199 | print(vertical.draw())
200 | ```
201 |
202 | 위의 예제에서 `VerticalShapes` 는 박스형 `Shape` 요소의 배열인 `[any Shape]` 로 `shapes` 의 타입을 선언합니다. 배열에 각 요소는 다른 타입이 올 수 있고 각 타입은 `Shape` 프로토콜을 준수해야 합니다. 이런 런타임 유연성을 제공하기위해 Swift 는 필요할 때 간접 참조 수준을 추가합니다 - 이런 간접 참조를 _박스 (box)_ 라고 부르며, 성능 비용 (performance cost) 을 가지고 있습니다.
203 |
204 | `VerticalShapes` 타입에는 `Shape` 프로토콜에 의해 요구되는 메서드, 프로퍼티, 그리고 서브 스크립트를 사용할 수 있습니다. 예를 들어, `VerticalShapes` 에 `draw()` 메서드는 배열의 각 요소의 `draw()` 메서드를 호출합니다. `Shape` 는 `draw()` 메서드를 요구하므로 이 메서드는 사용 가능합니다. 반대로, `Shape` 에 의해 요구되지 않은 삼각형 (triangle) 에 `size` 프로퍼티, 또는 다른 프로퍼티 또는 메서드를 접근하려고 하면 에러가 발생합니다.
205 |
206 | `shapes` 를 사용할 수 있는 세가지 타입이 있습니다:
207 |
208 | - `struct VerticalShapes` 와 `var shapes: [S]` 을 작성해 제너릭을 사용하여, 특정 모양 타입의 요소로 배열을 만들고, 특정 타입의 식별자가 배열로 상호작용하도록 노출됩니다.
209 |
210 | - `var shapes: [some Shape]` 을 작성해 투명한 타입을 사용하여, 특정 모양 타입의 요소로 배열을 만들고, 특정 타입의 식별자는 숨깁니다.
211 |
212 | - `var shapes: [any Shape]` 을 작성해 박스형 프로토콜 타입을 사용하여, 다른 타입의 요소로 저장할 수 있는 배열을 만들고, 이런 타입의 식별자는 숨깁니다.
213 |
214 | 이 경우 박스형 프로토콜 타입은 `VerticalShapes` 의 호출자가 다른 종류의 모양을 혼합할 수 있는 유일한 접근 방식입니다.
215 |
216 | 박스형 값 (boxed value) 의 타입을 알고 있는 경우에 `as` 캐스트를 사용할 수 있습니다. 예를 들어:
217 |
218 | ```swift
219 | if let downcastTriangle = vertical.shapes[0] as? Triangle {
220 | print(downcastTriangle.size)
221 | }
222 | // Prints "5"
223 | ```
224 |
225 | 더 자세한 내용은 [다운 캐스팅 (Downcasting)](type-casting.md#다운-캐스팅-downcasting) 을 참고 바랍니다.
226 |
227 | ## 불투명한 타입과 박스형 프로토콜 타입의 차이점 \(Differences Between Opaque Types and Boxed Protocol Types\)
228 |
229 | 불투명한 타입을 반환하는 것은 함수의 반환 타입으로 박스형 프로토콜 타입을 사용하는 것과 매우 유사하지만 이 두 종류의 반환 타입은 타입 정체성을 유지하는지 여부가 다릅니다. 불투명한 타입은 하나의 특정 타입을 참조하지만 함수 호출자는 어떤 타입인지 볼 수 없습니다. 박스형 프로토콜 타입은 프로토콜을 준수하는 모든 타입을 참조할 수 있습니다. 일반적으로 박스형 프로토콜 타입은 저장하는 값의 기본 타입에 대해 더 많은 유연성을 제공하고 불투명한 타입을 사용하면 이러한 기본 타입에 대해 더 강력한 보증을 할 수 있습니다.
230 |
231 | 예를 들어 다음은 불투명한 반환 타입 대신에 반환 타입으로 박스형 프로토콜 타입을 사용하는 `flip(_:)` 의 버전입니다:
232 |
233 | ```swift
234 | func protoFlip(_ shape: T) -> Shape {
235 | return FlippedShape(shape: shape)
236 | }
237 | ```
238 |
239 | `protoFlip(_:)` 의 버전은 `flip(_:)` 과 같은 본문을 가지고 항상 같은 타입의 값을 반환합니다. `flip(_:)` 과 다르게 `protoFlip(_:)` 이 반환하는 값은 항상 같은 타입을 가질 필요가 없으며 `Shape` 프로토콜을 준수하기만 하면 됩니다. 달리 말하면 `protoFlip(_:)` 은 `flip(_:)` 이 만든 것보다 더 느슨한 API 계약을 만듭니다. 이것은 여러 타입의 값을 반환하는 유연성을 보유합니다:
240 |
241 | ```swift
242 | func protoFlip(_ shape: T) -> Shape {
243 | if shape is Square {
244 | return shape
245 | }
246 |
247 | return FlippedShape(shape: shape)
248 | }
249 | ```
250 |
251 | 개정된 코드의 버전은 전달되는 모양에 따라 `Shape` 인스턴스 또는 `FlippedShape` 인스턴스를 반환합니다. 이 함수에 의해 반환된 2개의 뒤집힌 모양은 완전히 다른 타입을 가집니다. 이 함수의 다른 유효한 버전은 같은 모양의 여러 인스턴스를 뒤집을 때 다른 타입의 값을 반환할 수 있습니다. `protoFlip(_:)` 의 구체적이지 않은 반환 타입은 타입 정보에 의존하는 많은 작업이 반환된 값에서 사용할 수 없음을 의미합니다. 예를 들어 이 함수에 의해 반환된 결과를 비교하는 `==` 연산자를 작성할 수 없습니다.
252 |
253 | ```swift
254 | let protoFlippedTriangle = protoFlip(smallTriangle)
255 | let sameThing = protoFlip(smallTriangle)
256 | protoFlippedTriangle == sameThing // Error
257 | ```
258 |
259 | 예제의 마지막 라인에서 몇가지 이유로 에러가 발생합니다. 즉각적인 문제는 `Shape` 는 프로토콜 요구사항의 부분으로 `==` 연산자를 포함하지 않습니다. 이것을 추가하려고 하면 다음 문제는 `==` 연산자는 좌항과 우항 인수의 타입을 알아야 합니다. 이러한 종류의 연산자는 일반적으로 프로토콜을 채택하는 구체적인 타입과 일치하는 `Self` 타입의 인수를 사용하지만 프로토콜에 `Self` 요구사항을 추가하면 프로토콜을 타입으로 사용할 때 발생하는 타입 삭제가 허용되지 않습니다.
260 |
261 | 함수의 반환 타입으로 박스형 프로토콜 타입을 사용하면 프로토콜을 준수하는 모든 타입을 유연하게 반환할 수 있습니다. 그러나 이러한 유연성의 대가는 반환된 값에 대해 일부 작업을 수행할 수 없습니다. 이 예제는 박스형 프로토콜 타입을 사용하여 보존되지 않는 특정 타입 정보에 따라 `==` 연산자를 사용할 수 없는 것을 보여줍니다.
262 |
263 | 이 접근 방식의 다른 문제는 모양 변형이 중첩되지 않습니다. 삼각형을 뒤집은 결과는 `Shape` 타입의 값이고 `protoFlip(_:)` 함수는 `Shape` 프로토콜을 준수하는 일부 타입의 인수를 가집니다. 그러나 박스형 프로토콜 타입의 값은 `protoFlip(_:)` 에 의해 반환된 값은 `Shape` 를 준수하지 않으므로 프로토콜을 준수하지 않습니다. 여러 변형을 적용하는 `protoFlip(protoFlip(smallTriangle))` 같은 코드는 뒤집힌 모양이 `protoFlip(_:)` 에 대해 유효하지 않은 인수입니다.
264 |
265 | 반대로 불투명한 타입은 기본 타입의 정체성을 보존합니다. Swift는 연관된 타입을 유추할 수 있으므로 박스형 프로토콜 타입을 반환값으로 사용할 수 없는 위치에 불투명한 반환값을 사용할 수 있습니다. 예를 들어 다음은 [제너릭 \(Generics\)](generics.md) 의 `Container` 프로토콜의 버전입니다:
266 |
267 | ```swift
268 | protocol Container {
269 | associatedtype Item
270 | var count: Int { get }
271 | subscript(i: Int) -> Item { get }
272 | }
273 | extension Array: Container { }
274 | ```
275 |
276 | 프로토콜은 연관된 타입을 가지고 있으므로 함수의 반환 타입으로 `Container` 를 사용할 수 없습니다. 또한 제너릭 타입이 필요한지 추론하기 위해 함수 본문의 외부에 충분한 정보가 없으므로 제너릭 반환 타입의 제약조건으로 사용할 수 없습니다.
277 |
278 | ```swift
279 | // Error: Protocol with associated types can't be used as a return type.
280 | func makeProtocolContainer(item: T) -> Container {
281 | return [item]
282 | }
283 |
284 | // Error: Not enough information to infer C.
285 | func makeProtocolContainer(item: T) -> C {
286 | return [item]
287 | }
288 | ```
289 |
290 |
293 |
294 | 반환 타입으로 불투명한 타입 `some Container` 을 사용하면 함수는 컨테이너를 반환하지만 컨테이너의 타입 지정을 거부하므로 원하는 API가 표현됩니다:
295 |
296 | ```swift
297 | func makeOpaqueContainer(item: T) -> some Container {
298 | return [item]
299 | }
300 | let opaqueContainer = makeOpaqueContainer(item: 12)
301 | let twelve = opaqueContainer[0]
302 | print(type(of: twelve))
303 | // Prints "Int"
304 | ```
305 |
306 | `twelve` 의 타입은 `Int` 로 유추되며 이것은 불투명한 타입이 타입 추론이 동작한다는 것을 보여줍니다. `makeOpaqueContainer(item:)` 의 구현에서 불투명한 컨테이너의 기본 타입은 `[T]` 입니다. 이 경우에 `T` 는 `Int` 이므로 반환값은 정수의 배열이고 `Item` 연관된 타입은 `Int` 로 유추됩니다. `Container` 에서 서브 스크립트는 `twelve` 의 타입도 `Int` 로 유추된다는 의미의 `Item` 을 반환합니다.
307 |
308 | ## 불투명한 파라미터 타입 (Opaque Parameter Types)
309 |
310 | `some`을 사용하여 불투명한 타입을 반환하는 것 외에도,
311 | 함수, 서브스크립트, 초기화 구문의
312 | 파라미터 타입에도 `some`을 사용할 수 있습니다.
313 | 그러나 파라미터 타입에서 `some`을 사용하는 것은
314 | 불투명한 타입이 아니라 단순히 제네릭을 위한 더 짧은 문법일 뿐입니다.
315 | 예를 들어
316 | 아래의 두 함수는 동일한 의미를 가집니다:
317 |
318 | ```swift
319 | func drawTwiceGeneric(_ shape: SomeShape) -> String {
320 | let drawn = shape.draw()
321 | return drawn + "\n" + drawn
322 | }
323 |
324 | func drawTwiceSome(_ shape: some Shape) -> String {
325 | let drawn = shape.draw()
326 | return drawn + "\n" + drawn
327 | }
328 | ```
329 |
330 | `drawTwiceGeneric(_:)` 함수는
331 | `SomeShape`이라는 제너릭 타입 파라미터를 선언하고,
332 | 이 타입이 `Shape` 프로토콜을 준수해야 한다는 제약을 가집니다.
333 | `drawTwiceSome(_:)` 함수는
334 | 파라미터 타입으로 `some Shape`를 사용합니다.
335 | 이는 함수에 대해 새로운 이름 없는 제너릭 타입 파라미터를 생성하며,
336 | 해당 타입이 `Shape` 프로토콜을 준수해야 한다는 제약을 가집니다.
337 | 제너릭 타입은 이름이 없기 때문에
338 | 함수 내 다른 곳에서 이를 참조할 수 없습니다.
339 |
340 | 여러 파라미터의 타입 앞에 `some`을 사용하면,
341 | 각 제너릭 타입은 서로 독립적입니다.
342 | 예를 들어:
343 |
344 | ```swift
345 | func combine(shape s1: some Shape, with s2: some Shape) -> String {
346 | return s1.draw() + "\n" + s2.draw()
347 | }
348 |
349 | combine(smallTriangle, trapezoid)
350 | ```
351 |
352 | `combine(shape:with:)` 함수에서
353 | 첫 번째와 두 번째 파라미터의 타입은
354 | 모두 `Shape` 프로토콜을 준수해야 하지만,
355 | 두 파라미터가 동일한 타입일 필요는 없습니다.
356 | `combine(shape:with:)`를 호출할 때,
357 | 삼각형과 사다리꼴처럼
358 | 서로 다른 두 도형을 전달할 수 있습니다.
359 |
360 | [제너릭 (Generics)](./generics.md) 챕터에서 설명된
361 | 명명된 제너릭 타입 파라미터의 문법과 다르게,
362 | 이 간단한 문법은 제너릭 `where` 절이나 동일한 타입(`==`) 제약을
363 | 포함할 수 없습니다.
364 | 또한
365 | 매우 복잡한 제약을 표현할 때
366 | 이 간단한 문법을 사용하면 코드의 가독성이 떨어질 수 있습니다.
--------------------------------------------------------------------------------
/language-guide-1/optional-chaining.md:
--------------------------------------------------------------------------------
1 | # 옵셔널 체이닝 \(Optional Chaining\)
2 |
3 | 언래핑 없이 옵셔널 값의 멤버에 접근합니다.
4 |
5 | _옵셔널 체이닝 \(Optional chaining\)_ 은 현재 `nil` 일 수 있는 옵셔널 인 프로퍼티, 메서드, 그리고 서브 스크립트를 조회하고 호출하기 위한 프로세스 입니다. 옵셔널에 값이 포함되어 있으면 프로퍼티, 메서드, 또는 서브 스크립트는 호출에 성공합니다. 옵셔널이 `nil` 이면 프로퍼티, 메서드, 또는 서브 스크립트 호출은 `nil` 을 반환합니다. 여러 조회는 함께 연결될 수 있고 체인에 어느 부분이라도 `nil` 이면 전체 체인은 실패합니다.
6 |
7 | > Note
8 | > Swift에서 옵셔널 체이닝은 Objective-C에서 메시징 `nil` 과 유사하지만 모든 타입에 대해 동작하고 성공 또는 실패 여부를 확인할 수 있습니다.
9 |
10 | ## 강제 언래핑의 대안으로 옵셔널 체이닝 \(Optional Chaining as an Alternative to Forced Unwrapping\)
11 |
12 | 프로퍼티, 메서드 또는 서브 스크립트를 호출하려는 옵셔널 값 뒤에 물음표 \(`?`\)를 배치하여 옵셔널 체이닝을 지정합니다. 이것은 값에 강제 언래핑을 하기 위해 옵셔널 값 뒤에 느낌표 \(`!`\)를 배치하는 것과 유사합니다. 이것의 주요 차이점은 옵셔널이 `nil` 일 때 옵셔널 체이닝은 실패하는 반면에 강제 언래핑은 런타임 에러가 발생합니다.
13 |
14 | 옵셔널 체이닝은 `nil` 값에 대해 호출될 수 있다는 사실을 반영하기 위해 조회하는 프로퍼티, 메서드, 또는 서브 스크립트가 옵셔널 값이 아닌 값을 반환하더라도 항상 옵셔널 값으로 반환합니다. 옵셔널 반환 값으로 옵셔널 체이닝 호출이 성공 \(반환된 옵셔널 체이닝에 값이 포함됨\)했는지 실패 \(반환된 옵셔널 값은 `nil`\)했는지 확인할 수 있습니다.
15 |
16 | 특히 옵셔널 체이닝 호출의 결과는 예상되는 반환값과 동일한 타입이지만 옵셔널로 래핑됩니다. 일반적으로 `Int` 로 반환하는 프로퍼티는 옵셔널 체이닝을 통해 접근하면 `Int?` 를 반환합니다.
17 |
18 | 다음의 코드들은 옵셔널 체이닝이 강제 언래핑과 어떻게 다른지 보여주고 성공여부를 확인할 수 있도록 합니다.
19 |
20 | 첫번째, `Person` 과 `Residence` 라는 2개의 클래스는 정의되어 있습니다:
21 |
22 | ```swift
23 | class Person {
24 | var residence: Residence?
25 | }
26 |
27 | class Residence {
28 | var numberOfRooms = 1
29 | }
30 | ```
31 |
32 | `Residence` 인스턴스는 기본값이 `1` 인 `numberOfRooms` 라는 `Int` 프로퍼티를 가지고 있습니다. `Person` 인스턴스는 `Residence?` 타입의 옵셔널 `residence` 프로퍼티를 가지고 있습니다.
33 |
34 | 새로운 `Person` 인스턴스를 생성하면 `residence` 프로퍼티는 옵셔널 규칙에 따라 `nil` 로 초기화 됩니다. 아래의 코드에서 `john` 은 `nil` 의 `residence` 프로퍼티 값을 가지고 있습니다:
35 |
36 | ```swift
37 | let john = Person()
38 | ```
39 |
40 | 값에 강제 언래핑을 하기 위해 `residence` 뒤에 느낌표를 배치하여 사람의 `residence` 에 `numberOfRooms` 프로퍼티를 접근하면 `residence` 값이 없기 때문에 런타임 에러가 발생합니다:
41 |
42 | ```swift
43 | let roomCount = john.residence!.numberOfRooms
44 | // this triggers a runtime error
45 | ```
46 |
47 | `John.residence` 가 `nil` 값이 아니고 `roomCount` 에 방의 적절한 숫자를 포함한 `Int` 로 설정하면 위의 코드는 정상동작 합니다. 그러나 `residence` 가 `nil` 이면 이 코드는 항상 런타임 에러가 발생합니다.
48 |
49 | 옵셔널 체이닝은 `numberOfRooms` 의 값에 접근하기 위한 대안으로 제공합니다. 옵셔널 체이닝을 사용하기 위해 느낌표 위치에 물음표를 사용합니다:
50 |
51 | ```swift
52 | if let roomCount = john.residence?.numberOfRooms {
53 | print("John's residence has \(roomCount) room(s).")
54 | } else {
55 | print("Unable to retrieve the number of rooms.")
56 | }
57 | // Prints "Unable to retrieve the number of rooms."
58 | ```
59 |
60 | 이것은 Swift가 옵셔널 `residence` 프로퍼티를 "체인"하고 `residence` 가 존재하면 `numberOfRooms` 값을 조회하도록 합니다.
61 |
62 | `numberOfRooms` 접근하기 위한 시도는 실패할 수 있으므로 옵셔널 체이닝은 `Int?` 타입이나 "옵셔널 `Int`"의 값을 반환합니다. 위 예제에서 처럼 `residence` 가 `nil` 일 경우 `numberOfRooms` 접근이 불가능 한 사실을 반영하기 위해 옵셔널 `Int` 는 `nil` 입니다. 옵셔널 `Int` 는 언래핑 한 정수에 옵셔널 바인딩으로 접근되고 `roomCount` 상수에 옵셔널이 아닌 값을 할당합니다.
63 |
64 | `numberOfRooms` 가 옵셔널 `Int` 가 아니더라도 마찬가지입니다. 옵셔널 체인으로 조회 된다는 것은 `numberOfRooms` 호출은 항상 `Int` 대신 `Int?` 를 반환한다는 의미입니다.
65 |
66 | 더이상 `nil` 값을 갖지 않기 위해 `john.residence` 에 `Residence` 인스턴스를 할당할 수 있습니다:
67 |
68 | ```swift
69 | john.residence = Residence()
70 | ```
71 |
72 | `john.residence` 는 `nil` 이 아닌 실제 `Residence` 인스턴스를 포함합니다. 이전 처럼 같은 옵셔널 체이닝으로 `numberOfRooms` 에 접근하면 기본 `numberOfRooms` 값인 `1` 의 `Int?` 를 반환할 것입니다:
73 |
74 | ```swift
75 | if let roomCount = john.residence?.numberOfRooms {
76 | print("John's residence has \(roomCount) room(s).")
77 | } else {
78 | print("Unable to retrieve the number of rooms.")
79 | }
80 | // Prints "John's residence has 1 room(s)."
81 | ```
82 |
83 | ## 옵셔널 체이닝에 대한 모델 클래스 정의 \(Defining Model Classes for Optional Chaining\)
84 |
85 | 하나 이상의 레벨 깊이 인 프로퍼티, 메서드, 그리고 서브 스크립트를 호출하기 위해 옵셔널 체이닝을 사용할 수 있습니다. 타입 호환되는 복잡한 모델 내에서 하위 프로퍼티로 내려갈 수 있으며 해당 하위 프로퍼티에 프로퍼티, 메서드, 그리고 서브 스크립트에 접근 가능한지 확인할 수 있습니다.
86 |
87 | 아래의 코드는 여러 레벨 옵셔널 체이닝의 예를 포함하여 몇몇의 후속 예제에서 사용할 4개의 모델 클래스를 정의합니다. 이 클래스는 관련 프로퍼티, 메서드, 그리고 서브 스크립트를 가지는 `Room` 과 `Address` 클래스를 추가하여 위의 `Person` 과 `Residence` 모델을 확장합니다.
88 |
89 | `Person` 클래스는 이전과 같게 정의됩니다:
90 |
91 | ```swift
92 | class Person {
93 | var residence: Residence?
94 | }
95 | ```
96 |
97 | `Residence` 클래스는 이전보다 더 복잡합니다. 이제 `Residence` 클래스는 `[Room]` 타입의 빈 배열을 가지고 초기화 되는 `rooms` 라는 변수 프로퍼티를 정의합니다:
98 |
99 | ```swift
100 | class Residence {
101 | var rooms: [Room] = []
102 | var numberOfRooms: Int {
103 | return rooms.count
104 | }
105 | subscript(i: Int) -> Room {
106 | get {
107 | return rooms[i]
108 | }
109 | set {
110 | rooms[i] = newValue
111 | }
112 | }
113 | func printNumberOfRooms() {
114 | print("The number of rooms is \(numberOfRooms)")
115 | }
116 | var address: Address?
117 | }
118 | ```
119 |
120 | 이 `Residence` 버전은 `Room` 인스턴스의 배열을 저장하기 때문에 `numberOfRooms` 프로퍼티는 저장된 프로퍼티가 아닌 계산된 프로퍼티로 구현됩니다. 계산된 `numberOfRooms` 프로퍼티는 `rooms` 배열에서 `count` 프로퍼티의 값을 반환합니다.
121 |
122 | `rooms` 배열에 접근하는 짧은 구문을 위해 `Residence` 는 `rooms` 배열에 요청된 인덱스로 방에 접근을 제공하는 읽기-쓰기 서브 스크립트를 제공합니다.
123 |
124 | 이 `Residence` 는 주택에 있는 방의 갯수를 출력하는 `printNumberOfRooms` 라는 메서드도 제공합니다.
125 |
126 | 마지막으로 `Residence` 는 `Address?` 타입을 가지는 `address` 라는 옵셔널 프로퍼티를 정의합니다. 이 프로퍼티에 대한 `Address` 클래스 타입은 아래에 정의되어 있습니다.
127 |
128 | `rooms` 배열에 사용된 `Room` 클래스는 `name` 이라는 프로퍼티와 적절한 방 이름을 프로퍼티에 설정하는 초기화 구문을 가진 클래스 입니다:
129 |
130 | ```swift
131 | class Room {
132 | let name: String
133 | init(name: String) { self.name = name }
134 | }
135 | ```
136 |
137 | 이 모델의 마지막 클래스는 `Address` 라 합니다. 이 클래스는 `String?` 타입의 3개의 옵셔널 프로퍼티를 가집니다. `buildingName` 과 `buildingNumber` 인 첫번째, 두번째 프로퍼티는 주소의 부분으로 특정 건물을 식별하기 위한 대안책입니다. 세번째 프로퍼티 인 `street` 는 주소에 대한 도로의 이름으로 사용됩니다:
138 |
139 | ```swift
140 | class Address {
141 | var buildingName: String?
142 | var buildingNumber: String?
143 | var street: String?
144 | func buildingIdentifier() -> String? {
145 | if let buildingNumber, let street {
146 | return "\(buildingNumber) \(street)"
147 | } else if buildingName != nil {
148 | return buildingName
149 | } else {
150 | return nil
151 | }
152 | }
153 | }
154 | ```
155 |
156 | 또한 `Address` 클래스는 `String?` 의 반환 타입을 가지는 `buildingIdentifier()` 라는 메서드도 제공합니다. 이 메서드는 주소의 프로퍼티를 확인하고 값이 있으면 `buildingName` 을 반환하거나 둘다 값이 있으면 `street` 과 연결된 `buildingNumber` 를 반환하고 값이 없으면 `nil` 을 반환합니다.
157 |
158 | ## 옵셔널 체이닝을 통해 프로퍼티 접근 \(Accessing Properties Through Optional Chaining\)
159 |
160 | [강제 언래핑의 대안으로 옵셔널 체이닝 \(Optional Chaining as an Alternative to Forced Unwrapping\)](optional-chaining.md#optional-chaining-as-an-alternative-to-forced-unwrapping) 에서 설명 했듯이 옵셔널 값의 프로퍼티에 접근하고 프로퍼티 접근이 성공하면 검사하기 위해 옵셔널 체이닝을 사용할 수 있습니다.
161 |
162 | 새로운 `Person` 인스턴스를 생성하기 위해 위에 정의된 클래스를 사용하고 이전처럼 `numberOfRooms` 프로퍼티에 접근합니다:
163 |
164 | ```swift
165 | let john = Person()
166 | if let roomCount = john.residence?.numberOfRooms {
167 | print("John's residence has \(roomCount) room(s).")
168 | } else {
169 | print("Unable to retrieve the number of rooms.")
170 | }
171 | // Prints "Unable to retrieve the number of rooms."
172 | ```
173 |
174 | `John.residence` 는 `nil` 이기 때문에 옵셔널 체이닝은 이전과 같이 실패를 호출합니다.
175 |
176 | 옵셔널 체이닝을 통해 프로퍼티의 값을 설정할 수 있습니다:
177 |
178 | ```swift
179 | let someAddress = Address()
180 | someAddress.buildingNumber = "29"
181 | someAddress.street = "Acacia Road"
182 | john.residence?.address = someAddress
183 | ```
184 |
185 | 이 예제에서 `john.residence` 가 `nil` 이기 때문에 `john.residence` 에 `address` 프로퍼티에 설정하기 위한 시도는 실패 할 것입니다.
186 |
187 | 이 할당은 `=` 연산자의 우항의 코드는 평가되지 않으므로 옵셔널 체이닝의 일부입니다. 이전 예제에서 상수에 접근하는 것은 어떠한 영향도 없기 때문에 `someAddress` 가 평가되지 않는다는 것을 쉽게 파악할 수 없습니다. 아래의 리스트는 같은 할당을 수행하지만 주소를 생성하기 위해 함수를 사용합니다. 이 함수는 값을 반환하기 전에 "Function was called"를 출력하여 `=` 연산자 우항이 평가되었음을 알 수 있습니다.
188 |
189 | ```swift
190 | func createAddress() -> Address {
191 | print("Function was called.")
192 |
193 | let someAddress = Address()
194 | someAddress.buildingNumber = "29"
195 | someAddress.street = "Acacia Road"
196 |
197 | return someAddress
198 | }
199 | john.residence?.address = createAddress()
200 | ```
201 |
202 | 아무것도 출력되지 않기 때문에 `createAddress()` 함수가 호출되지 않음을 알 수 있습니다.
203 |
204 | ## 옵셔널 체이닝을 통한 함수 호출 \(Calling Methods Through Optional Chaining\)
205 |
206 | 옵셔널 값의 메서드를 호출하고 메서드 호출이 성공적인지 확인하기 위해 옵셔널 체이닝을 사용할 수 있습니다. 해당 메서드가 반환값을 정의하지 않아도 사용할 수 있습니다.
207 |
208 | `Residence` 클래스에 `printNumberOfRooms()` 메서드는 `numberOfRooms` 의 현재값을 출력합니다. 메서드는 아래와 같습니다:
209 |
210 | ```swift
211 | func printNumberOfRooms() {
212 | print("The number of rooms is \(numberOfRooms)")
213 | }
214 | ```
215 |
216 | 이 메서드는 반환 타입이 지정되지 않았습니다. 그러나 반환 타입이 없는 함수와 메서드는 [반환값 없는 함수 \(Functions Without Return Values\)](functions.md#functions-without-return-values) 에서 설명했듯이 `Void` 의 암시적 반환 타입을 가지고 있습니다. 이것은 `()` 의 값 또는 빈 튜플을 반환한다는 의미입니다.
217 |
218 | 옵셔널 체이닝을 사용하여 옵셔널 값에 대해 메서드를 호출하면 반환값은 옵셔널 타입이기 때문에 메서드의 반환 타입은 `Void` 가 아닌 `Void?` 입니다. 메서드가 반환값을 정의하지 않았어도 `printNumberOfRooms()` 메서드 호출이 가능한지 `if` 구문을 사용하여 확인할 수 있습니다. `printNumberOfRooms` 호출의 반환값을 `nil` 과 비교하여 메서드 호출이 성공했는지 확인합니다:
219 |
220 | ```swift
221 | if john.residence?.printNumberOfRooms() != nil {
222 | print("It was possible to print the number of rooms.")
223 | } else {
224 | print("It was not possible to print the number of rooms.")
225 | }
226 | // Prints "It was not possible to print the number of rooms."
227 | ```
228 |
229 | 옵셔널 체이닝을 통해 프로퍼티를 설정하려는 경우에도 마찬가지입니다. [옵셔널 체이닝을 통해 프로퍼티 접근 \(Accessing Properties Through Optional Chaining\)](optional-chaining.md#accessing-properties-through-optional-chaining) 에서 위의 예제는 `residence` 프로퍼티가 `nil` 이지만 `John.residence` 에 대해 `address` 값을 설정 하려고 합니다. 옵셔널 체이닝을 통해 프로퍼티를 설정하려는 모든 시도는 `nil` 과 비교하여 프로퍼티에 값이 성공적으로 설정되었는지 확인할 수 있는 `Void?` 타입의 값을 반환합니다:
230 |
231 | ```swift
232 | if (john.residence?.address = someAddress) != nil {
233 | print("It was possible to set the address.")
234 | } else {
235 | print("It was not possible to set the address.")
236 | }
237 | // Prints "It was not possible to set the address."
238 | ```
239 |
240 | ## 옵셔널 체이닝을 통한 서브 스크립트 접근 \(Accessing Subscripts Through Optional Chaining\)
241 |
242 | 옵셔널 값의 서브 스크립트에서 값을 조회하고 설정하고 해당 서브 스크립트 호출이 성공했는지 확인하기 위해 옵셔널 체이닝을 사용할 수 있습니다.
243 |
244 | > Note
245 | > 옵셔널 체이닝을 통해 옵셔널 값의 서브 스크립트에 접근할 때 물음표는 서브 스크립트의 대괄호 전에 위치합니다. 옵셔널 체이닝 물음표는 항상 옵셔널 표현구 부분의 바로 다음에 위치합니다.
246 |
247 | 아래의 예제는 `Residence` 클래스에 정의된 서브 스크립트를 사용하여 `john.residence` 프로퍼티에 `rooms` 배열의 첫번째 방 이름을 조회합니다. 현재 `john.residence` 는 `nil` 이므로 서브 스크립트 호출은 실패합니다:
248 |
249 | ```swift
250 | if let firstRoomName = john.residence?[0].name {
251 | print("The first room name is \(firstRoomName).")
252 | } else {
253 | print("Unable to retrieve the first room name.")
254 | }
255 | // Prints "Unable to retrieve the first room name."
256 | ```
257 |
258 | 서브 스크립트 호출에 옵셔널 체이닝 물음표는 `john.residence` 가 옵셔널 체이닝이 시도되는 옵셔널 값이기 때문에 `john.residence` 다음과 대괄호 전에 위치합니다.
259 |
260 | 유사하게 옵셔널 체이닝을 사용하여 서브 스크립트를 통해 새로운 값을 설정할 수 있습니다:
261 |
262 | ```swift
263 | john.residence?[0] = Room(name: "Bathroom")
264 | ```
265 |
266 | `residence` 가 현재 `nil` 이므로 서브 스크립트 설정은 실패합니다.
267 |
268 | `rooms` 배열에 하나 이상의 `Room` 인스턴스 가지고 `john.residence` 에 실제 `Residence` 인스턴스를 생성하고 할당하면 옵셔널 체이닝으로 `Residence` 서브 스크립트를 사용하여 `rooms` 배열의 항목을 접근할 수 있습니다:
269 |
270 | ```swift
271 | let johnsHouse = Residence()
272 | johnsHouse.rooms.append(Room(name: "Living Room"))
273 | johnsHouse.rooms.append(Room(name: "Kitchen"))
274 | john.residence = johnsHouse
275 |
276 | if let firstRoomName = john.residence?[0].name {
277 | print("The first room name is \(firstRoomName).")
278 | } else {
279 | print("Unable to retrieve the first room name.")
280 | }
281 | // Prints "The first room name is Living Room."
282 | ```
283 |
284 | ### 옵셔널 타입에 서브 스크립트 접근 \(Accessing Subscripts of Optional Type\)
285 |
286 | 서브 스크립트가 Swift의 `Dictionary` 타입의 키 서브 스크립트와 같이 옵셔널 타입의 값을 반환하는 경우 옵셔널 반환값을 연결하기 위해 서브 스크립트의 닫는 대괄호 _뒤에_ 물음표를 추가합니다:
287 |
288 | ```swift
289 | var testScores = ["Dave": [86, 82, 84], "Bev": [79, 94, 81]]
290 | testScores["Dave"]?[0] = 91
291 | testScores["Bev"]?[0] += 1
292 | testScores["Brian"]?[0] = 72
293 | // the "Dave" array is now [91, 82, 84] and the "Bev" array is now [80, 94, 81]
294 | ```
295 |
296 | 위의 예제는 `String` 키를 `Int` 값 배열에 매핑하는 2개의 키-값 쌍을 포함하는 `testScores` 라는 딕셔너리를 정의합니다. 이 예제는 `"Dave"` 배열에 첫번째 항목에 `91` 을 설정하고 `"Bev"` 배열에 첫번째 항목에 `1` 을 더하고 `"Brian"` 키에 대한 배열에 첫번째 항목에 값을 설정하기 위해 옵셔널 체이닝을 사용합니다. `testScores` 딕셔너리는 `"Dave"` 와 `"Bev"` 에 대한 키를 가지고 있으므로 첫번째 두번째 호출은 성공합니다. `testScores` 딕셔너리는 `"Brian"` 에 대한 키를 가지고 있지 않으므로 세번째 호출은 실패합니다.
297 |
298 | ## 여러 수준의 체인연결 \(Linking Multiple Levels of Chaining\)
299 |
300 | 여러 수준의 옵셔널 체이닝을 연결하여 모델 내에서 프로퍼티, 메서드, 그리고 서브 스크립트로 깊게 접근할 수 있습니다. 그러나 여러 수준의 옵셔널 체이닝은 반환된 값에 더 많은 수준의 옵션성을 추가하지 않습니다.
301 |
302 | 다른 말로 표현하면:
303 |
304 | * 조회하려는 타입이 옵셔널이 아니면 옵셔널 체이닝 때문에 옵셔널이 됩니다.
305 | * 조회하려는 타입이 _이미_ 옵셔널이면 체이닝 때문에 _더 많은_ 옵셔널이 되지 않습니다.
306 |
307 | 따라서:
308 |
309 | * 옵셔널 체이닝으로 `Int` 값을 조회하려고 하면 사용된 체이닝의 수준과 상관없이 항상 `Int?` 가 반환됩니다.
310 | * 유사하게 옵셔널 체이닝으로 `Int?` 값을 조회하려고 하면 사용된 체이닝의 수준과 상관없이 항상 `Int?` 가 반환됩니다.
311 |
312 | 아래의 예제는 `john` 의 `residence` 프로퍼티에 `address` 프로퍼티에 `street` 프로퍼티를 접근합니다. 여기에서는 `residence` 와 `address` 프로퍼티를 통해 연결하기 위해 _2단계_ 수준의 옵셔널 체이닝이 사용되며 둘 다 옵셔널 타입입니다:
313 |
314 | ```swift
315 | if let johnsStreet = john.residence?.address?.street {
316 | print("John's street name is \(johnsStreet).")
317 | } else {
318 | print("Unable to retrieve the address.")
319 | }
320 | // Prints "Unable to retrieve the address."
321 | ```
322 |
323 | `john.residence` 의 값은 현재 유효한 `Residence` 인스턴스를 가지고 있습니다. 그러나 `John.residence.address` 의 값은 현재 `nil` 입니다. 이것 때문에 `john.residence?.address?.street` 을 호출하면 실패합니다.
324 |
325 | 위의 예에서는 `street` 프로퍼티의 값을 조회하려고 합니다. 이 프로퍼티의 타입은 `String?` 입니다. 따라서 `john.residence?.address?.street` 의 반환값은 2단계 옵셔널 체이닝이 프로퍼티의 옵셔널 타입에 적용되었지만 `String?` 입니다.
326 |
327 | `john.residence.address` 에 대한 값으로 `Address` 인스턴스를 설정하고 주소의 `street` 프로퍼티에 대해 값을 설정하면 여러 수준의 옵셔널 체이닝을 통해 `street` 프로퍼티의 값에 접근할 수 있습니다:
328 |
329 | ```swift
330 | let johnsAddress = Address()
331 | johnsAddress.buildingName = "The Larches"
332 | johnsAddress.street = "Laurel Street"
333 | john.residence?.address = johnsAddress
334 |
335 | if let johnsStreet = john.residence?.address?.street {
336 | print("John's street name is \(johnsStreet).")
337 | } else {
338 | print("Unable to retrieve the address.")
339 | }
340 | // Prints "John's street name is Laurel Street."
341 | ```
342 |
343 | 이 예제에서 `john.residence` 의 값은 현재 유효한 `Residence` 인스턴스 이므로 `john.residence` 에 `address` 프로퍼티에 값을 설정하는 것이 가능합니다.
344 |
345 | ## 옵셔널 반환값으로 메서드 체이닝 \(Chaining on Methods with Optional Return Values\)
346 |
347 | 이전 예제는 어떻게 옵셔널 체이닝을 통해 옵셔널 타입의 프로퍼티의 값을 조회해야 하는지 보여줍니다. 옵셔널 체이닝은 또한 옵셔널 타입의 값을 반환하는 메서드를 호출하고 필요하다면 메서드의 반환값을 연결하기 위해 사용할 수 있습니다.
348 |
349 | 아래의 예제는 옵셔널 체이닝을 통해 `Address` 클래스의 `buildingIdentifier()` 메서드를 호출합니다. 이 메서드는 `String?` 타입의 값을 반환합니다. 위에서 설명 했듯이 옵셔널 체이닝 이후 이 메서드 호출의 반환 타입은 `String?` 입니다:
350 |
351 | ```swift
352 | if let buildingIdentifier = john.residence?.address?.buildingIdentifier() {
353 | print("John's building identifier is \(buildingIdentifier).")
354 | }
355 | // Prints "John's building identifier is The Larches."
356 | ```
357 |
358 | 메서드의 반환값에서 더 옵셔널 체이닝을 수행하려면 메서드의 소괄호 _다음에_ 옵셔널 체이닝 물음표를 위치시키면 됩니다:
359 |
360 | ```swift
361 | if let beginsWithThe =
362 | john.residence?.address?.buildingIdentifier()?.hasPrefix("The") {
363 | if beginsWithThe {
364 | print("John's building identifier begins with \"The\".")
365 | } else {
366 | print("John's building identifier does not begin with \"The\".")
367 | }
368 | }
369 | // Prints "John's building identifier begins with "The"."
370 | ```
371 |
372 | > Note
373 | > 위의 예제에서 연결하려는 옵셔널 값이 `buildingIdentifier()` 메서드 자체가 아닌 `buildingIdentifier()` 메서드의 반환값이므로 소괄호 _뒤에_ 옵셔널 체이닝 물음표를 위치시킵니다.
374 |
375 |
--------------------------------------------------------------------------------
/language-guide-1/structures-and-classes.md:
--------------------------------------------------------------------------------
1 | # 구조체와 클래스 \(Structures and Classes\)
2 |
3 | 데이터를 캡슐화하는 사용자 정의 타입을 모델링합니다.
4 |
5 | _구조체 \(Structures\)_ 와 _클래스 \(classes\)_ 는 프로그램 코드의 구성 요소가 되는 범용의 유연한 구조입니다. 상수, 변수, 그리고 함수를 정의하는 것과 같은 구문을 사용하여 구조체와 클래스에 프로퍼티와 메서드를 기능적으로 추가할 수 있습니다.
6 |
7 | 다른 프로그래밍 언어와 달리 Swift는 사용자 정의 구조체와 클래스에 대해 별도의 인터페이스와 구현 파일을 만들 필요가 없습니다. Swift에서 단일 파일로 구조체 또는 클래스를 정의하면 해당 클래스 또는 구조체에 대한 외부 인터페이스가 자동으로 다른 코드에서 사용할 수 있습니다.
8 |
9 | > Note
10 | > 클래스의 인스턴스는 전통적으로 _객체 \(object\)_ 라고 알고 있습니다. 그러나 Swift 구조체와 클래스는 다른 언어보다 기능적으로 훨씬 가깝고 이 챕터의 대부분은 클래스 또는 구조체 타입의 인스턴스에 적용되는 기능을 설명합니다. 이 때문에 좀 더 일반적인 용어인 _인스턴스 \(instance\)_ 가 사용됩니다.
11 |
12 | ## 구조체와 클래스의 비교 \(Comparing Structures and Classes\)
13 |
14 | Swift에서 구조체와 클래스는 공통점이 많습니다. 둘다 아래의 내용이 가능합니다:
15 |
16 | * 값을 저장하는 프로퍼티 정의
17 | * 기능 제공을 위한 메서드 정의
18 | * 서브 스크립트 구문을 사용하여 값에 접근을 제공하는 서브 스크립트 정의
19 | * 초기화 상태를 설정하기 위한 초기화 정의
20 | * 기본 구현을 넘어 기능적 확장을 위한 확장
21 | * 특정 종류의 표준 기능을 제공하는 프로토콜 준수
22 |
23 | 더 자세한 내용은 [프로퍼티 \(Properties\)](properties.md), [메서드 \(Methods\)](methods.md), [서브 스크립트 \(Subscripts\)](subscripts.md), [초기화 \(Initialization\)](initialization.md), [확장 \(Extensions\)](extensions.md), [프로토콜 \(Protocols\)](protocols.md) 을 참고 바랍니다.
24 |
25 | 클래스는 구조체에 없는 추가적인 기능이 있습니다:
26 |
27 | * 상속을 사용하면 한 클래스가 다른 클래스의 특성을 상속할 수 있습니다.
28 | * 타입 캐스팅을 사용하면 런타임에 클래스 인스턴스의 타입을 확인하고 해석할 수 있습니다.
29 | * 초기화 해제 구문 \(Deinitializers\) 을 사용하면 클래스의 인스턴스가 할당된 리소스를 해제할 수 있도록 합니다.
30 | * 참조 카운팅은 하나 이상의 클래스 인스턴스 참조를 허락합니다.
31 |
32 | 더 자세한 내용은 [상속 \(Inheritance\)](inheritance.md), [타입 캐스팅 \(Type Casting\)](type-casting.md), [초기화 해제 \(Deinitialization\)](deinitialization.md), [자동 참조 카운팅 \(Automatic Reference Counting\)](automatic-reference-counting.md) 을 참고 바랍니다.
33 |
34 | 클래스가 지원하는 추가 기능은 복잡성이 증가합니다. 일반적인 지침으로는 추론하기 쉬운 구조체를 선호하고 적절하거나 필요할 때 클래스를 사용합니다. 실질적으로 정의하는 대부분의 사용자 정의 타입이 구조체와 열거형 이라는 것을 의미합니다. 더 자세한 비교는 [구조체와 클래스 선택 \(Choosing Between Structures and Classes\)](https://developer.apple.com/documentation/swift/choosing_between_structures_and_classes) 을 참고 바랍니다.
35 |
36 | > Note
37 | > 클래스와 액터 \(actor\) 는 많은 동일한 특성과 동작을 공유합니다. 액터에 대한 자세한 내용은 [동시성 \(Concurrency\)](concurrency.md) 을 참고 바랍니다.
38 |
39 | ### 정의 구문 \(Definition Syntax\)
40 |
41 | 구조체와 클래스는 유사한 정의 구문을 가지고 있습니다. 구조체는 `struct` 키워드로 클래스는 `class` 키워드로 시작합니다. 둘다 중괄호 안에 전체 정의가 위치합니다:
42 |
43 | ```swift
44 | struct SomeStructure {
45 | // structure definition goes here
46 | }
47 | class SomeClass {
48 | // class definition goes here
49 | }
50 | ```
51 |
52 | > Note
53 | > 새로운 구조체 또는 클래스를 정의할 때마다 새로운 Swift 타입을 정의합니다. 표준 Swift 타입 \(`String`, `Int`, `Bool` 과 같은\)의 대소문자와 일치하도록 타입 `UpperCamelCase` 이름 \(`SomeStructure` 와 `SomeClass` 와 같이\)을 지정하십시오. 프로퍼티와 메서드는 타입 이름과 구분을 위해 `lowerCamelCase` 이름 \(`frameRate` 와 `incrementCount` 와 같이\)으로 지정하십시오.
54 |
55 | 다음은 구조체 정의와 클래스 정의의 예입니다:
56 |
57 | ```swift
58 | struct Resolution {
59 | var width = 0
60 | var height = 0
61 | }
62 | class VideoMode {
63 | var resolution = Resolution()
64 | var interlaced = false
65 | var frameRate = 0.0
66 | var name: String?
67 | }
68 | ```
69 |
70 | 위 예제는 픽셀기반의 화면 해상도를 설명하는 `Resolution` 이라는 새로운 구조체를 정의합니다. 이 구조체는 `width` 와 `height` 라 불리는 저장된 프로퍼티를 가지고 있습니다. 저장된 프로퍼티는 구조체 또는 클래스의 일부로 묶여 저장되는 상수 또는 변수입니다. 이 두 프로퍼티는 정수값 `0` 으로 초기값이 설정되므로 `Int` 타입으로 유추됩니다.
71 |
72 | 위 예제는 비디오 화면을 위한 특정 비디오 모드를 설명하는 `VideoMode` 라는 새로운 클래스를 정의합니다. 이 클래스는 4개의 저장된 프로퍼티를 가지고 있습니다. 첫번재 `resolution` 은 `Resolution` 의 프로퍼티 타입으로 유추되는 새로운 `Resolution` 구조체 인스턴스로 초기화 됩니다. 다른 3가지 프로퍼티 경우 새로운 `VideoMode` 인스턴스는 `interlaced` 설정은 `false` \("비인터레이스 비디오"\)로 재생 프레임 속도는 `0.0` 으로 그리고 `name` 이라는 옵셔널 `String` 값으로 초기화 됩니다. `name` 프로퍼티는 옵셔널 타입이므로 자동적으로 `nil` 기본값으로 주어지거나 "`name` 값 없음" 으로 주어집니다.
73 |
74 | ### 구조체와 클래스 인스턴스 \(Structure and Class Instances\)
75 |
76 | `Resolution` 구조체 정의와 `VideoMode` 클래스 정의는 오직 `Resolution` 또는 `VideoMode` 의 모양만 설명합니다. 자체적인 해상도 또는 비디오 모드에 대해 설명하지 않습니다. 그렇게 하려면 구조체 또는 클래스의 인스턴스 생성이 필요합니다.
77 |
78 | 인스턴스 생성 구문은 구조체와 클래스 모두 매우 유사합니다:
79 |
80 | ```swift
81 | let someResolution = Resolution()
82 | let someVideoMode = VideoMode()
83 | ```
84 |
85 | 구조체와 클래스 모두 새로운 인스턴스를 위해 초기화 구문을 사용합니다. 초기화 구문의 가장 간단한 형태는 `Resolution()` 또는 `VideoMode()` 와 같이 클래스 또는 구조체 타입 이름 뒤에 빈 소괄호를 붙여 사용하는 것입니다. 이렇게 하면 모든 프로퍼티가 기본값으로 초기화되는 클래스 또는 구조체의 새로운 인스턴스를 생성합니다. 클래스와 구조체 초기화에 대한 자세한 내용은 [초기화 \(Initialization\)](initialization.md) 를 참고 바랍니다.
86 |
87 | ### 프로퍼티 접근 \(Accessing Properties\)
88 |
89 | _점 구문 \(dot syntax\)_ 을 사용하여 인스턴스의 프로퍼티에 접근할 수 있습니다. 점 구문은 인스턴스 이름 뒤에 구분자 \(`.`\)로 분리하고 공백 없이 프로퍼티 이름을 작성합니다:
90 |
91 | ```swift
92 | print("The width of someResolution is \(someResolution.width)")
93 | // Prints "The width of someResolution is 0"
94 | ```
95 |
96 | 이 예제에서 `someResolution.width` 는 `someResolution` 에 프로퍼티 `width` 를 참조하고 기본값 `0` 을 반환합니다.
97 |
98 | `VideoMode` 의 `resolution` 프로퍼티에 `width` 프로퍼티와 같이 서브 프로퍼티에 접근할 수 있습니다:
99 |
100 | ```swift
101 | print("The width of someVideoMode is \(someVideoMode.resolution.width)")
102 | // Prints "The width of someVideoMode is 0"
103 | ```
104 |
105 | 변수 프로퍼티에 새로운 값을 할당하기 위해 점 구문을 사용할 수 있습니다:
106 |
107 | ```swift
108 | someVideoMode.resolution.width = 1280
109 | print("The width of someVideoMode is now \(someVideoMode.resolution.width)")
110 | // Prints "The width of someVideoMode is now 1280"
111 | ```
112 |
113 | ### 구조체 타입에 대한 멤버별 초기화 구문 \(Memberwise Initializers for Structure Types\)
114 |
115 | 모든 구조체는 새로운 구조체 인스턴스의 멤버 프로퍼티를 초기화 할 때 사용할 수 있는 자동적으로 생성된 _멤버별 초기화 구문 \(memberwise intializer\)_ 을 가지고 있습니다. 새로운 인스턴스에 프로퍼티 초기값은 이름으로 멤버별 초기화에 전달될 수 있습니다:
116 |
117 | ```swift
118 | let vga = Resolution(width: 640, height: 480)
119 | ```
120 |
121 | 구조체와 반대로 클래스 인스턴스는 멤버별 초기화를 받지 않습니다. 자세한 설명은 [초기화 \(Initialization\)](initialization.md) 을 참고 바랍니다.
122 |
123 | ## 구조체와 열거형은 값 타입 \(Structures and Enumerations Are Value Types\)
124 |
125 | _값 타입 \(value type\)_ 은 변수 또는 상수에 할당될 때나 함수에 전달될 때 _복사_ 되는 값인 타입입니다.
126 |
127 | 실제로 값 타입에 대해 이전 챕터에서 광범위하게 다뤘습니다. 실제로 Swift에서 정수, 부동 소수점, 부울, 문자열, 배열 그리고 딕셔너리와 같은 기본 타입의 모두는 값 타입이고 구조체로 구현되어 있습니다.
128 |
129 | Swift에서 모든 구조체와 열거형은 값 타입입니다. 이것은 생성한 구조체와 열거형 인스턴스와 프로퍼티로 포함된 모든 값 타입은 코드에서 전달될 때 복사된다는 의미입니다.
130 |
131 | > Note
132 | > 배열, 딕셔너리, 문자열과 같은 Swift 표준 라이브러리에 정의된 콜렉션은 최적화를 사용하여 복사 성능 비용을 줄입니다. 즉시 복사본을 만드는 대신에 이러한 콜렉션은 원본 인스턴스와 복사본 간에 요소가 저장된 메모리를 공유합니다. 콜렉션의 복사본 중 하나가 수정되면 요소는 수정되기 직전에 복사됩니다. 코드에서 보이는 동작은 항상 바로 복사가 일어나는 것처럼 보입니다.
133 |
134 | 이전 예제에서의 `Resolution` 구조체를 사용하는 다음 예제를 살펴봅시다:
135 |
136 | ```swift
137 | let hd = Resolution(width: 1920, height: 1080)
138 | var cinema = hd
139 | ```
140 |
141 | 이 예제는 `hd` 라는 상수를 선언하고 풀 HD 비디오 \(1920 픽셀 너비와 1080 픽셀 높이\)의 너비와 높이를 초기화하는 `Resolution` 인스턴스를 설정합니다.
142 |
143 | 그리고 나서 `cinema` 라는 변수를 선언하고 `hd` 의 현재 값을 설정합니다. `Resolution` 은 구조체 이므로 기존 인스턴스의 _복사본_ 이 만들어지고 이 새 복사본에 `cinema` 가 할당됩니다. `hd` 와 `cinema` 가 현재 같은 너비와 높이를 가지지만 2개는 완벽하게 다른 인스턴스 입니다.
144 |
145 | 다음으로 `cinema` 의 `width` 프로퍼티를 디지털 시네마 프로젝션에 사용되는 약간 더 넓은 2K 표준 \(2048 픽셀 너비와 1080 픽셀 높이\)으로 수정됩니다:
146 |
147 | ```swift
148 | cinema.width = 2048
149 | ```
150 |
151 | `cinema` 의 `width` 프로퍼티를 체크하면 `2048` 로 바뀐 것을 확인할 수 있습니다:
152 |
153 | ```swift
154 | print("cinema is now \(cinema.width) pixels wide")
155 | // Prints "cinema is now 2048 pixels wide"
156 | ```
157 |
158 | 그러나 기존 `hd` 인스턴스의 `width` 프로퍼티는 `1920` 의 기존값을 그대로 가지고 있습니다:
159 |
160 | ```swift
161 | print("hd is still \(hd.width) pixels wide")
162 | // Prints "hd is still 1920 pixels wide"
163 | ```
164 |
165 | `cinema` 에 `hd` 에 현재값이 주어졌을 때 `hd` 에 저장된 _값_ 은 새로운 `cinema` 인스턴스에 복사됩니다. 마지막 결과는 숫자값을 포함한 2개의 완벽히 분리된 인스턴스 입니다. 그러나 분리된 인스턴스이기 때문에 아래의 그림과 같이 `cinema` 에 너비를 `2048` 로 설정해도 `hd` 에 저장된 너비에는 영향을 주지 않습니다:
166 |
167 | 
168 |
169 | 열거형에서도 같은 동작이 이뤄집니다:
170 |
171 | ```swift
172 | enum CompassPoint {
173 | case north, south, east, west
174 | mutating func turnNorth() {
175 | self = .north
176 | }
177 | }
178 | var currentDirection = CompassPoint.west
179 | let rememberedDirection = currentDirection
180 | currentDirection.turnNorth()
181 |
182 | print("The current direction is \(currentDirection)")
183 | print("The remembered direction is \(rememberedDirection)")
184 | // Prints "The current direction is north"
185 | // Prints "The remembered direction is west"
186 | ```
187 |
188 | `rememberedDirection` 은 `currentDirection` 에 값이 할당될 때 실질적으로 복사본이 설정됩니다. 이후에 `currentDirection` 에 값을 변경해도 `rememberedDirection` 에 저장된 원래 값의 복사본에는 영향을 주지 않습니다.
189 |
190 | ## 클래스는 참조 타입 \(Classes Are Reference Types\)
191 |
192 | 값 타입과 반대로 _참조 타입 \(reference types\)_ 은 변수 또는 상수에 할당될 때나 함수로 전달될 때 복사되지 않습니다. 복사본 대신에 존재하는 같은 인스턴스에 대한 참조가 사용됩니다.
193 |
194 | 다음은 위에 정의된 `VideoMode` 를 사용하는 예입니다:
195 |
196 | ```swift
197 | let tenEighty = VideoMode()
198 | tenEighty.resolution = hd
199 | tenEighty.interlaced = true
200 | tenEighty.name = "1080i"
201 | tenEighty.frameRate = 25.0
202 | ```
203 |
204 | 이 예제는 `tenEighty` 라는 새로운 상수를 선언하고 `VideoMode` 클래스의 새로운 인스턴스를 참조하도록 설정합니다. 비디오 모드는 이전에 `1920` x `1080` 의 HD 해상도의 복사본이 할당됩니다. 인터레이스로 설정되고 이름을 `"1080i"` 로 설정하고 프레임 속도를 초당 `25.0` 프레임으로 설정합니다.
205 |
206 | 다음으로 `tenEighty` 는 `alsoTenEighty` 라는 새로운 상수에 할당되고 `alsoTenEighty` 의 프레임 속도를 수정합니다:
207 |
208 | ```swift
209 | let alsoTenEighty = tenEighty
210 | alsoTenEighty.frameRate = 30.0
211 | ```
212 |
213 | 클래스는 참조 타입이므로 `tenEighty` 와 `alsoTenEighty` 는 실질적으로 _같은_ `VideoMode` 인스턴스를 참조합니다. 실제로는 아래 그림과 같이 같은 하나의 인스턴스에 다른 2개의 이름을 가지고 있는 것입니다:
214 |
215 | 
216 |
217 | `tenEighty` 의 `frameRate` 프로퍼티를 체크하면 `VideoMode` 인스턴스에서 `30.0` 의 새로운 프레임 속도가 올바르게 설정된 것을 보여줍니다:
218 |
219 | ```swift
220 | print("The frameRate property of tenEighty is now \(tenEighty.frameRate)")
221 | // Prints "The frameRate property of tenEighty is now 30.0"
222 | ```
223 |
224 | 이 예제는 참조 타입이 어떻게 추론하기 어려울 수 있는지 보여줍니다. `tenEighty` 와 `alsoTenEighty` 가 프로그램 코드가 멀리 떨어져 있다면 비디오 모드가 변경되는 모든 방법을 찾기 어려울 수 있습니다. `tenEighty` 를 사용할 때마다 `alsoTenEighty` 를 사용하는 코드를 생각해야 하며 그 반대도 마찬가지 입니다. 반대로 값 타입은 동일한 값과 상호작용하는 모든 코드가 소스 파일에 가까이 있기 때문에 추론하기가 더 쉽습니다.
225 |
226 | `tenEighty` 와 `alsoTenEighty` 는 변수가 아닌 _상수_ 로 선언됩니다. 그러나 `tenEighty` 와 `alsoTenEighty` 상수 자체는 실제로 변경되지 않으므로 `tenEighty.frameRate` 와 `alsoTenEighty.frameRate` 는 여전히 변경 가능합니다. `tenEighty` 와 `alsoTenEighty` 자체는 `VideoMode` 인스턴스를 "저장"하지 않습니다. 대신에 `VideoMode` 인스턴스를 둘다 _참조_ 합니다. 변경되는 것은 `VideoMode` 에 대한 상수 참조의 값이 아니라 `VideoMode` 의 `frameRate` 프로퍼티 입니다.
227 |
228 | ### 식별 연산자 \(Identity Operators\)
229 |
230 | 클래스는 참조 타입이기 때문에 클래스의 같은 단일 인스턴스에 참조하는 여러개의 상수와 변수가 가능합니다 \(구조체와 열거형은 상수 또는 변수 또는 함수에 전달할 때 항상 복사되기 때문에 클래스와 같지 않습니다\).
231 |
232 | 2개의 상수 또는 변수가 클래스의 같은 인스턴스를 참조하는지 확인하는 것이 유용할 수 있습니다. 이를 위해 Swift는 2가지 식별 연산자를 제공합니다:
233 |
234 | * 동일 인스턴스 \(Identical to\) \(`===`\)
235 | * 동일하지 않은 인스턴스 \(Not identical to\) \(`!==`\)
236 |
237 | 이 연산자를 사용하여 2개의 상수 또는 변수가 하나의 동일한 인스턴스를 참조하는지 확인할 수 있습니다:
238 |
239 | ```swift
240 | if tenEighty === alsoTenEighty {
241 | print("tenEighty and alsoTenEighty refer to the same VideoMode instance.")
242 | }
243 | // Prints "tenEighty and alsoTenEighty refer to the same VideoMode instance."
244 | ```
245 |
246 | _동일 인스턴스_ \(3개의 등호로 표시 또는 `===`\)는 _같음 \(equal to\)_ \(2개의 등호로 표시 또는 `==`\)과 같다는 의미는 아닙니다. _동일 인스턴스_ 는 클래스 타입의 2개의 상수 또는 변수가 동일한 클래스 인스턴스를 참조한다는 의미입니다. _같음_ 은 두 인스턴스의 값이 동일하거나 동등하다는 것을 의미합니다.
247 |
248 | 커스텀 구조체와 클래스를 정의할 때 두 인스턴스가 같은지의 여부를 결정하는 것은 사용자의 몫입니다. `==` 와 `!=` 연산자의 자체 구현 선언의 프로세스는 [등가 연산자 \(Equivalence Operators\)](advanced-operators.md#equivalence-operators) 에 자세히 설명되어 있습니다.
249 |
250 | ### 포인터 \(Pointers\)
251 |
252 | C, C++, 또는 Objective-C에 경험이 있다면 메모리의 주소를 참조하기 위해 _포인터 \(pointers\)_ 를 사용한다는 것을 알고 있을 것입니다. 일부 참조 타입의 인스턴스를 참조하기 위한 Swift 상수 또는 변수는 C의 포인터와 유사하지만 메모리의 주소에 대한 직접적인 포인터가 아니며 포인터 표시를 위해 별표 \(`*`\)를 작성할 필요가 없습니다. 대신에 이러한 참조는 Swift의 다른 상수 또는 변수처럼 정의됩니다. Swift 표준 라이브러리는 포인터와 직접 상호작용이 필요한 경우 사용할 수 있는 포인터와 버퍼 타입을 제공합니다. 자세한 내용은 [수동 메모리 관리 \(Manual Memory Management\)](https://developer.apple.com/documentation/swift/swift_standard_library/manual_memory_management) 를 참고 바랍니다.
253 |
254 |
--------------------------------------------------------------------------------
/language-guide-1/subscripts.md:
--------------------------------------------------------------------------------
1 | # 서브 스크립트 \(Subscripts\)
2 |
3 | 콜렉션의 요소에 접근합니다.
4 |
5 | 클래스, 구조체, 그리고 열거형은 콜렉션, 리스트, 또는 시퀀스의 멤버 요소에 접근할 수 있는 단축키인 _서브 스크립트 \(subscripts\)_ 를 정의할 수 있습니다. 설정과 검색을 위한 별도의 메서드 없이 인덱스로 값을 설정하고 조회하기 위해 서브 스크립트를 사용합니다. 예를 들어 `someArray[index]` 로 `Array` 인스턴스에 요소를 접근하고 `someDictionary[key]` 로 `Dictionary` 인스턴스에 요소를 접근합니다.
6 |
7 | 단일 타입을 위한 여러개 서브 스크립트를 정의할 수 있고 사용할 적절한 서브 스크립트 오버로드는 서브 스크립트에 전달하는 인덱스 값의 타입에 따라 선택됩니다. 서브 스크립트는 단일 차원으로 제한되지 않고 사용자 타입에 맞춰 여러개의 입력 파라미터로 서브 스크립트를 정의할 수 있습니다.
8 |
9 | ## 서브 스크립트 구문 \(Subscript Syntax\)
10 |
11 | 서브 스크립트를 사용하면 인스턴스 이름 뒤에 대괄호에 하나 이상의 값을 작성하여 타입의 인스턴스를 조회할 수 있습니다. 이 구문은 인스턴스 메서드 구문과 계산된 프로퍼티 구문과 유사합니다. `subscript` 키워드로 서브 스크립트 정의를 작성하고 인스턴스 메서드와 같은 방법으로 하나 이상의 입력 파라미터와 반환 타입을 작성합니다. 인스턴스 메서드와 다르게 서브 스크립트는 읽기-쓰기 또는 읽기전용이 될 수 있습니다. 이러한 동작은 계산된 프로퍼티와 같은 방법으로 getter와 setter를 통해 동작합니다:
12 |
13 | ```swift
14 | subscript(index: Int) -> Int {
15 | get {
16 | // Return an appropriate subscript value here.
17 | }
18 | set(newValue) {
19 | // Perform a suitable setting action here.
20 | }
21 | }
22 | ```
23 |
24 | `newValue` 의 타입은 서브 스크립트의 반환 값과 동일합니다. 계산된 프로퍼티와 마찬가지로 setter의 `(newValue)` 파라미터를 지정하지 않도록 선택할 수 있습니다. 파라미터를 지정하지 않으면 setter에 `newValue` 라는 기본 파라미터가 제공됩니다.
25 |
26 | 읽기전용 계산된 프로퍼티와 마찬가지로 `get` 키워드와 그것의 중괄호를 삭제하여 읽기전용 서브 스크립트를 쉽게 선언할 수 있습니다:
27 |
28 | ```swift
29 | subscript(index: Int) -> Int {
30 | // Return an appropriate subscript value here.
31 | }
32 | ```
33 |
34 | 다음은 정수의 _n_-배-테이블을 표시하기 위한 `TimesTable` 구조체를 정의하는 읽기전용 서브 스크립트 구현의 예입니다:
35 |
36 | ```swift
37 | struct TimesTable {
38 | let multiplier: Int
39 | subscript(index: Int) -> Int {
40 | return multiplier * index
41 | }
42 | }
43 | let threeTimesTable = TimesTable(multiplier: 3)
44 | print("six times three is \(threeTimesTable[6])")
45 | // Prints "six times three is 18"
46 | ```
47 |
48 | 이 예제에서 `TimesTable` 의 새로운 인스턴스는 3배 테이블을 표시하기 위해 생성됩니다. 인스턴스의 `multiplier` 파라미터를 사용하는 값으로 구조체의 `initializer` 에 `3` 의 값을 전달하여 나타냅니다.
49 |
50 | `threeTimesTable[6]` 에 대한 호출에 보여준 것처럼 서브 스크립트를 호출하여 `threeTimesTable` 인스턴스를 조회할 수 있습니다. 이것은 `3` 의 `6` 배인 `18` 의 값을 반환하는 3배 테이블에서 6번째 값을 요청합니다.
51 |
52 | > Note
53 | > _n_-배-테이블은 수학적 규칙을 기반으로 합니다. `threeTimesTable[someIndex]` 를 새로운 값을 설정하는 것은 적절하지 않으므로 `TimesTable` 의 서브 스크립트는 읽기전용 서브 스크립트로 정의됩니다.
54 |
55 | ## 서브 스크립트 사용 \(Subscript Usage\)
56 |
57 | "서브 스크립트"의 정확한 의미는 사용되는 컨텍스트에 따라 다릅니다. 일반적으로 서브 스크립트는 콜렉션, 리스트, 또는 시퀀스에 멤버 요소에 접근하는 바로가기로 사용됩니다. 특정 클래스 또는 구조체의 기능에 가장 적합한 방식으로 서브 스크립트를 자유롭게 구현할 수 있습니다.
58 |
59 | 예를 들어 Swift의 `Dictionary` 타입은 `Dictionary` 인스턴스에 저장된 값을 설정하고 조회하기 위해 서브 스크립트를 구현합니다. 서브 스크립트 대괄호 내에 딕셔너리의 키 타입의 키를 제공하고 딕셔너리의 값 타입의 값을 서브 스크립트에 할당하여 딕셔너리에 값을 설정할 수 있습니다:
60 |
61 | ```swift
62 | var numberOfLegs = ["spider": 8, "ant": 6, "cat": 4]
63 | numberOfLegs["bird"] = 2
64 | ```
65 |
66 | 위의 예제는 `numberOfLegs` 라는 변수를 정의하고 3개의 키-값 쌍을 포함하는 딕셔너리를 초기화합니다. `numberOfLegs` 딕셔너리의 타입은 `[String: Int]` 로 유추됩니다. 딕셔너리가 생성된 후에 이 예제는 딕셔너리에 `"bird"` 의 `String` 키와 `2` 의 `Int` 값을 추가하기 위해 서브 스크립트 할당을 사용합니다.
67 |
68 | `Dictionary` 서브 스크립트에 대한 자세한 내용은 [딕셔너리 접근과 수정 \(Accessing and Modifying a Dictionary\)](collection-types.md#accessing-and-modifying-a-dictionary) 을 참고 바랍니다.
69 |
70 | > Note
71 | > Swift의 `Dictionary` 타입은 _옵셔널_ 타입을 가지고 반환하는 서브 스크립트 인 키-값 서브 스크립트를 구현합니다. 위의 `numberOfLegs` 딕셔너리에서 키-값 서브 스크립트는 타입 `Int?` 또는 "옵셔널 int"의 값을 가지고 반환합니다. `Dictionary` 타입은 모든 키에 값이 있지 않다는 사실을 모델링 하고 키의 값에 `nil` 을 할당하여 키의 값을 삭제하는 방법을 제공하기 위해 옵셔널 서브 스크립트 타입을 사용합니다.
72 |
73 | ## 서브 스크립트 옵션 \(Subscript Options\)
74 |
75 | 서브 스크립트는 여러개의 입력 파라미터를 가질 수 있고 입력 파라미터는 어떤 타입도 가능합니다. 서브 스크립트는 어떤 타입도 반환할 수 있습니다.
76 |
77 | 함수 처럼 서브 스크립트는 [가변 파라미터 \(Variadic Parameters\)](functions.md#variadic-parameters) 와 [파라미터 기본값 \(Default Parameter Values\)](functions.md#default-parameter-values) 에서 설명 했듯이 가변 파라미터와 파라미터에 기본값을 가질 수 있습니다. 그러나 함수와 다르게 서브 스크립트는 in-out 파라미터를 사용할 수 없습니다.
78 |
79 | 클래스 또는 구조체는 필요한 만큼 서브 스크립트 구현과 값의 타입 또는 서브 스크립트 대괄호 내에서 포함된 값을 기반으로 추론하여 적절한 서브 스크립트를 제공할 수 있습니다. 이러한 여러개의 서브 스크립트 정의를 _서브 스크립트 오버로딩 \(subscript overloading\)_ 이라 합니다.
80 |
81 | 대부분 서브 스크립트는 하나의 파라미터를 가지지만 적절한 타입에 경우 여러개의 파라미터를 가진 서브 스크립트를 정의할 수도 있습니다. 다음의 예제는 `Double` 값의 2차 행렬을 나타내는 `Matrix` 구조체를 정의합니다. `Matrix` 구조체의 서브 스크립트는 2개의 정수 파라미터를 가집니다:
82 |
83 | ```swift
84 | struct Matrix {
85 | let rows: Int, columns: Int
86 | var grid: [Double]
87 | init(rows: Int, columns: Int) {
88 | self.rows = rows
89 | self.columns = columns
90 | grid = Array(repeating: 0.0, count: rows * columns)
91 | }
92 | func indexIsValid(row: Int, column: Int) -> Bool {
93 | return row >= 0 && row < rows && column >= 0 && column < columns
94 | }
95 | subscript(row: Int, column: Int) -> Double {
96 | get {
97 | assert(indexIsValid(row: row, column: column), "Index out of range")
98 | return grid[(row * columns) + column]
99 | }
100 | set {
101 | assert(indexIsValid(row: row, column: column), "Index out of range")
102 | grid[(row * columns) + column] = newValue
103 | }
104 | }
105 | }
106 | ```
107 |
108 | `Matrix` 는 `rows` 와 `columns` 라는 2개의 파라미터를 가지고 `Double` 타입의 `rows * columns` 값을 저장할 수 있는 큰 배열을 생성하는 초기화를 제공합니다. 행렬의 각 위치는 `0.0` 의 초기값이 주어집니다. 이를 위해 배열의 크기와 초기 셀 값 `0.0` 이 올바른 크기의 새로운 배열을 생성하고 초기화하는 배열 초기화에 전달됩니다. 이러한 초기화는 [기본값 배열 생성 \(Creating an Array with a Default Value\)](collection-types.md#creating-an-array-with-a-default-value) 에 자세히 설명되어 있습니다.
109 |
110 | 적절한 행과 열의 수를 초기화로 전달하여 새로운 `Matrix` 인스턴스를 생성할 수 있습니다:
111 |
112 | ```swift
113 | var matrix = Matrix(rows: 2, columns: 2)
114 | ```
115 |
116 | 위의 예제는 2행과 2열을 가지는 새로운 `Matrix` 인스턴스를 생성합니다. `Matrix` 인스턴스의 `grid` 배열은 왼쪽 상단에서 오른쪽 하단으로 읽는 것처럼 행렬의 평면화 버전입니다:
117 |
118 | 
119 |
120 | 행렬의 값은 콤마로 구분된 서브 스크립트에 행과 열 값을 전달하여 설정될 수 있습니다:
121 |
122 | ```swift
123 | matrix[0, 1] = 1.5
124 | matrix[1, 0] = 3.2
125 | ```
126 |
127 | 이 2개의 구문은 행렬의 우측 상단 \(`row` 가 `0` 이고 `column` 이 `1`\)에 `1.5` 값을 설정하고 좌측 하단 \(`row` 가 `1` 이고 `column` 이 `0`\)에 `3.2` 값을 설정하기 위해 서브 스크립트의 setter를 호출합니다:
128 |
129 | 
130 |
131 | `Matrix` 서브 스크립트의 getter와 setter 둘다 서브 스크립트의 `row` 와 `column` 값이 유효한지 판단하기 위해 어설션 \(assertion\)이 포함됩니다. 어설션을 지원하기 위해 `Matrix` 는 요청한 `row` 와 `column` 이 행렬의 범위안에 있는지를 판단하기 위해 `indexIsValid(row:column:)` 이라는 편리한 메서드를 포함합니다:
132 |
133 | ```swift
134 | func indexIsValid(row: Int, column: Int) -> Bool {
135 | return row >= 0 && row < rows && column >= 0 && column < columns
136 | }
137 | ```
138 |
139 | 어셜션은 행렬 범위를 넘어서 서브 스크립트를 접근하려고 하면 에러가 발생됩니다:
140 |
141 | ```swift
142 | let someValue = matrix[2, 2]
143 | // This triggers an assert, because [2, 2] is outside of the matrix bounds.
144 | ```
145 |
146 | ## 타입 서브 스크립트 \(Type Subscripts\)
147 |
148 | 위에서 설명했듯이 인스턴스 서브 스크립트는 특정 타입의 인스턴스를 호출하는 서브 스크립트 입니다. 타입 자체에서 호출되는 서브 스크립트도 정의할 수 있습니다. 이런 종류의 서브 스크립트를 _타입 서브 스크립트 \(type subscript\)_ 라고 합니다. `subscript` 키워드 전에 `static` 키워드를 작성하여 타입 서브 스크립트를 나타냅니다. 클래스는 하위 클래스가 수퍼 클래스의 서브 스크립트의 구현을 재정의 할 수 있게 대신 `class` 키워드를 사용할 수 있습니다. 아래 예제는 타입 서브 스크립트를 어떻게 정의하고 호출하는지 보여줍니다:
149 |
150 | ```swift
151 | enum Planet: Int {
152 | case mercury = 1, venus, earth, mars, jupiter, saturn, uranus, neptune
153 | static subscript(n: Int) -> Planet {
154 | return Planet(rawValue: n)!
155 | }
156 | }
157 | let mars = Planet[4]
158 | print(mars)
159 | ```
160 |
161 |
--------------------------------------------------------------------------------
/language-guide-1/type-casting.md:
--------------------------------------------------------------------------------
1 | # 타입 캐스팅 \(Type Casting\)
2 |
3 | 값의 런타임 타입을 정하고 타입의 정보를 제공합니다.
4 |
5 | _타입 캐스팅 \(Type casting\)_ 은 인스턴스의 타입을 확인하거나 해당 인스턴스를 자체 클래스 계층 구조의 다른 곳에서 다른 상위 클래스 또는 하위 클래스로써 취급하는 방법입니다.
6 |
7 | Swift에서 타입 캐스팅은 `is` 와 `as` 연산자로 구현됩니다. 이 두 연산자는 값의 타입을 확인하거나 값을 다른 타입으로 캐스트하는 간단하고 효과적인 방법을 제공합니다.
8 |
9 | [프로토콜 준수에 대한 검사 \(Checking for Protocol Conformance\)](protocols.md#checking-for-protocol-conformance) 에서 설명한대로 타입 캐스팅을 사용하여 타입이 프로토콜을 준수하는지 확인할 수도 있습니다.
10 |
11 | ## 타입 캐스팅을 위한 클래스 계층 정의 \(Defining a Class Hierarchy for Type Casting\)
12 |
13 | 클래스와 하위 클래스의 계층도와 함께 타입 캐스팅을 사용하여 특정 클래스 인스턴스의 타입을 확인하고 같은 계층도 내에서 다른 클래스로 인스턴스를 캐스트 할 수 있습니다. 아래의 세 코드는 타입 캐스팅의 예제에서 사용하기 위해 클래스의 계층도와 해당 클래스의 인스턴스를 포함하는 배열을 정의합니다.
14 |
15 | 첫번째 코드는 `MediaItem` 이라는 새로운 기본 클래스를 정의합니다. 이 클래스는 디지털 미디어 라이브러리에 나타나는 모든 종류의 항목에 대한 기본 기능을 제공합니다. 특히 `String` 타입의 `name` 프로퍼티와 `init(name:)` 초기화 구문을 선언합니다 \(영화와 노래를 포함하여 모든 미디어 항목은 이름을 가지고 있다고 가정합니다\).
16 |
17 | ```swift
18 | class MediaItem {
19 | var name: String
20 | init(name: String) {
21 | self.name = name
22 | }
23 | }
24 | ```
25 |
26 | 다음 코드는 `MediaItem` 의 두 개의 하위 클래스를 정의합니다. 첫번째 하위 클래스 `Movie` 는 영화 또는 필름에 대한 추가 정보를 캡슐화 합니다. 기본 `MediaItem` 클래스의 상위에 `director` 프로퍼티와 해당 초기화 구문을 추가합니다. 두번째 하위 클래스 `Song` 은 기본 클래스의 상위에 `artist` 프로퍼티와 초기화 구문을 추가합니다:
27 |
28 | ```swift
29 | class Movie: MediaItem {
30 | var director: String
31 | init(name: String, director: String) {
32 | self.director = director
33 | super.init(name: name)
34 | }
35 | }
36 |
37 | class Song: MediaItem {
38 | var artist: String
39 | init(name: String, artist: String) {
40 | self.artist = artist
41 | super.init(name: name)
42 | }
43 | }
44 | ```
45 |
46 | 마지막 코드는 두 개의 `Movie` 인스턴스와 세 개의 `Song` 인스턴스를 포함하는 `library` 라는 배열 상수를 생성합니다. `library` 배열의 타입은 배열 리터럴의 내용으로 초기화하여 추론됩니다. Swift의 타입 검사기는 `Movie` 와 `Song` 이 `MediaItem` 의 상위 클래스를 공통으로 가지고 있으므로 `library` 배열에 대해 `[MediaItem]` 타입으로 추론할 수 있습니다:
47 |
48 | ```swift
49 | let library = [
50 | Movie(name: "Casablanca", director: "Michael Curtiz"),
51 | Song(name: "Blue Suede Shoes", artist: "Elvis Presley"),
52 | Movie(name: "Citizen Kane", director: "Orson Welles"),
53 | Song(name: "The One And Only", artist: "Chesney Hawkes"),
54 | Song(name: "Never Gonna Give You Up", artist: "Rick Astley")
55 | ]
56 | // the type of "library" is inferred to be [MediaItem]
57 | ```
58 |
59 | `library` 에 저장된 항목은 여전히 `Movie` 와 `Song` 인스턴스 입니다. 그러나 이 배열의 항목을 반복하면 항목은 `Movie` 또는 `Song` 이 아닌 `MediaItem` 타입으로 받습니다. 기본 타입으로 작업을 하려면 아래에 설명된대로 타입을 확인하거나 다른 타입으로 다운캐스트 해야합니다.
60 |
61 | ## 타입 검사 \(Checking Type\)
62 |
63 | 인스턴스가 특정 하위 클래스 타입인지 확인하기 위해 _타입 검사 연산자 \(type check operator\)_ \(`is`\)를 사용합니다. 이 타입 검사 연산자는 인스턴스가 하위 클래스 타입이면 `true` 아니면 `false` 를 반환합니다.
64 |
65 | 아래의 예제는 `library` 배열에 `Movie` 와 `Song` 인스턴스의 숫자를 나타내는 두 개의 변수 `movieCount` 와 `songCount`를 정의합니다:
66 |
67 | ```swift
68 | var movieCount = 0
69 | var songCount = 0
70 |
71 | for item in library {
72 | if item is Movie {
73 | movieCount += 1
74 | } else if item is Song {
75 | songCount += 1
76 | }
77 | }
78 |
79 | print("Media library contains \(movieCount) movies and \(songCount) songs")
80 | // Prints "Media library contains 2 movies and 3 songs"
81 | ```
82 |
83 | 이 예제는 `library` 배열의 모든 항목을 통해 반복합니다. 반복문 실행 시에 `for`-`in` 루프는 배열에서 다음 `MediaItem` 을 `item` 상수에 설정합니다.
84 |
85 | `item is Movie` 는 현재 `MediaItem` 이 `Movie` 인스턴스이면 `true` 를 반환하고 아니면 `false` 를 반환합니다. 유사하게 `item is Song` 은 항목이 `Song` 인스턴스인지 확인합니다. `for`-`in` 루프의 마지막에 `movieCount` 와 `songCount` 의 값은 `MediaItem` 인스턴스에서 각 타입을 포함하는 카운트를 나타냅니다.
86 |
87 | ## 다운 캐스팅 \(Downcasting\)
88 |
89 | 특정 클래스 타입의 상수 또는 변수는 하위 클래스의 인스턴스를 참조할 수 있습니다. 이것이 필요하다고 생각하는 경우 _타입 캐스트 연산자 \(type cast operator\)_ \(`as?` 또는 `as!`\)를 사용하여 하위 클래스 타입으로 _다운 캐스트 \(downcast\)_ 할 수 있습니다.
90 |
91 | 다운 캐스팅은 실패할 수 있으므로 타입 캐스트 연산자는 2가지 다른 형태로 제공됩니다. 조건부 형식 `as?` 은 다운 캐스트를 하려고 할 때 타입의 옵셔널 값을 반환합니다. 강제 형식 `as!` 은 다운 캐스트를 시도하고 단일 복합 동작으로 강제 언래핑합니다.
92 |
93 | 다운 캐스트가 성공할지 확신이 없을 때 조건부 형식의 타입 캐스트 연산자 \(`as?`\)를 사용합니다. 이 연산자의 형식은 항상 옵셔널 값을 반환하고 다운 캐스트가 불가능하면 `nil` 을 반환합니다. 이것은 다운 캐스트의 성공여부를 확인하는 용도로도 사용 가능합니다.
94 |
95 | 다운 캐스트가 항상 성공할 것이라는 확신이 있을 때만 강제 형식의 타입 캐스트 연산자 \(`as!`\)를 사용해야 합니다. 이 연산자의 형식은 유효하지 않은 클래스 타입으로 다운 캐스트를 시도하면 런타임 에러가 발생합니다.
96 |
97 | 아래의 예제는 `library` 에 각 `MediaItem` 을 반복하고 각 항목에 대한 적절한 설명을 출력합니다. 이렇게 하려면 `MediaItem` 이 아닌 `Movie` 또는 `Song` 으로 각 항목에 접근해야 합니다. 이것은 설명을 사용하기 위해 `Movie` 또는 `Song` 의 `director` 또는 `artist` 프로퍼티에 접근할 수 있도록 하기위해 필요합니다.
98 |
99 | 이 예제는 배열의 각 항목은 `Movie` 또는 `Song` 일 수 있습니다. 각 항목에 사용할 실제 클래스를 미리 알지 못하므로 루프를 통해 매번 다운 캐스트를 확인하기 위해 타입 캐스트 연산자 \(`as?`\)의 조건부 형식을 사용하는 것이 적절합니다:
100 |
101 | ```swift
102 | for item in library {
103 | if let movie = item as? Movie {
104 | print("Movie: \(movie.name), dir. \(movie.director)")
105 | } else if let song = item as? Song {
106 | print("Song: \(song.name), by \(song.artist)")
107 | }
108 | }
109 |
110 | // Movie: Casablanca, dir. Michael Curtiz
111 | // Song: Blue Suede Shoes, by Elvis Presley
112 | // Movie: Citizen Kane, dir. Orson Welles
113 | // Song: The One And Only, by Chesney Hawkes
114 | // Song: Never Gonna Give You Up, by Rick Astley
115 | ```
116 |
117 | 이 예제는 `Movie` 로 현재 `item` 을 다운 캐스트 하는 것으로 시작합니다. `item` 은 `MediaItem` 인스턴스 이므로 `Movie` 일 수도 있고 마찬가지로 `Song` 일 수 있습니다. 또는 기본 `MediaItem` 일 수도 있습니다. 이 불확실성 때문에 타입 캐스트 연산자의 `as?` 형식은 하위 클래스 타입으로 다운 캐스트를 시도할 때 _옵셔널_ 값으로 반환합니다. `item as? Movie` 의 결과는 `Movie?` 타입 또는 "옵셔널 `Movie`" 입니다.
118 |
119 | 라이브러리 배열에 `Song` 인스턴스로 적용할 때 `Movie` 로 다운 캐스팅은 실패합니다. 이것을 대응하기 위해 위의 예제는 옵셔널 `Movie` 가 실제 값에 포함되어 있는지 확인하기 위해 \(다운 캐스트가 성공 되었는지 확인하기 위해\) 옵셔널 바인딩을 사용합니다. 이 옵셔널 바인딩은 "`if let movie = item as? Movie`" 로 작성되고 아래와 같이 읽을 수 있습니다:
120 |
121 | "`Movie` 로 `item` 은 접근하려고 합니다. 성공하면 반환된 옵셔널 `Movie` 를 `movie` 라는 새로운 임시 상수로 설정합니다."
122 |
123 | 다운 캐스팅이 성공하면 `movie` 의 프로퍼티는 `director` 의 이름을 포함하여 `Movie` 인스턴스에 대해 설명을 출력하는데 사용합니다. 유사한 원칙을 사용하여 `Song` 인스턴스를 확인하고 라이브러리에서 `Song` 을 찾을 때마다 `artist` 이름을 포함하여 적절한 설명을 출력하는데 사용합니다.
124 |
125 | > Note
126 | > 캐스팅은 실제로 인스턴스를 수정하거나 값을 변경하지 않습니다. 기본 인스턴스는 동일하게 유지됩니다. 캐스트된 타입의 인스턴스로 처리하고 접근 합니다.
127 |
128 | ## Any 와 AnyObject 에 대한 타입 캐스팅 \(Type Casting for Any and AnyObject\)
129 |
130 | Swift는 비특정 타입 작업을 위해 2개의 특별한 타입을 제공합니다:
131 |
132 | * `Any` 는 함수 타입을 포함하여 모든 타입의 인스턴스를 나타낼 수 있습니다.
133 | * `AnyObject` 는 모든 클래스 타입의 인스턴스를 나타낼 수 있습니다.
134 |
135 | 제공하는 동작과 기능이 명시적으로 필요한 경우에만 `Any` 와 `AnyObject` 를 사용합니다. 코드에서 작업할 것으로 예상되는 타입에 대해 구체적으로 지정하는 것이 항상 좋습니다.
136 |
137 | 다음은 함수 타입과 비 클래스 타입을 포함하여 다른 타입에 혼합으로 작업하기 위해 `Any` 를 사용하는 예제입니다. 이 예제는 `Any` 타입에 값을 저장할 수 있는 `things` 라는 배열을 생성합니다:
138 |
139 | ```swift
140 | var things: [Any] = []
141 |
142 | things.append(0)
143 | things.append(0.0)
144 | things.append(42)
145 | things.append(3.14159)
146 | things.append("hello")
147 | things.append((3.0, 5.0))
148 | things.append(Movie(name: "Ghostbusters", director: "Ivan Reitman"))
149 | things.append({ (name: String) -> String in "Hello, \(name)" })
150 | ```
151 |
152 | `things` 배열은 2개의 `Int` 값, 2개의 `Double` 값, 하나의 `String` 값, 하나의 `(Double, Double)` 타입의 튜플, "Ghostbusters" 영화, 그리고 `String` 값과 다른 `String` 값을 반환하는 클로저 표현식을 포함합니다.
153 |
154 | `Any` 또는 `AnyObject` 타입으로만 알려진 상수 또는 변수의 특정 타입을 알아보려면 `switch` 구문의 케이스로 `is` 또는 `as` 패턴을 사용할 수 있습니다. 아래의 예제는 `things` 배열에 항목을 반복하고 `switch` 구문으로 각 항목의 타입을 조회합니다. 몇몇의 `switch` 구문의 케이스는 일치된 값을 지정된 타입의 상수에 바인딩하여 해당 값을 출력할 수 있도록 합니다:
155 |
156 | ```swift
157 | for thing in things {
158 | switch thing {
159 | case 0 as Int:
160 | print("zero as an Int")
161 | case 0 as Double:
162 | print("zero as a Double")
163 | case let someInt as Int:
164 | print("an integer value of \(someInt)")
165 | case let someDouble as Double where someDouble > 0:
166 | print("a positive double value of \(someDouble)")
167 | case is Double:
168 | print("some other double value that I don't want to print")
169 | case let someString as String:
170 | print("a string value of \"\(someString)\"")
171 | case let (x, y) as (Double, Double):
172 | print("an (x, y) point at \(x), \(y)")
173 | case let movie as Movie:
174 | print("a movie called \(movie.name), dir. \(movie.director)")
175 | case let stringConverter as (String) -> String:
176 | print(stringConverter("Michael"))
177 | default:
178 | print("something else")
179 | }
180 | }
181 |
182 | // zero as an Int
183 | // zero as a Double
184 | // an integer value of 42
185 | // a positive double value of 3.14159
186 | // a string value of "hello"
187 | // an (x, y) point at 3.0, 5.0
188 | // a movie called Ghostbusters, dir. Ivan Reitman
189 | // Hello, Michael
190 | ```
191 |
192 | > Note
193 | > `Any` 타입은 옵셔널 타입을 포함하여 모든 타입의 값을 나타냅니다. Swift는 `Any` 타입의 값이 기대되는 곳에 옵셔널 값을 사용하면 경고를 줍니다. `Any` 값으로 옵셔널 값을 사용하는 것이 필요하다면 아래와 같이 `as` 연산자를 사용하여 명시적으로 옵셔널을 `Any` 로 캐스트 할 수 있습니다.
194 | >
195 | > ```swift
196 | > let optionalNumber: Int? = 3
197 | > things.append(optionalNumber) // Warning
198 | > things.append(optionalNumber as Any) // No warning
199 | > ```
200 |
201 |
--------------------------------------------------------------------------------
/language-reference/about-the-language-reference.md:
--------------------------------------------------------------------------------
1 | # 언어 참조에 대해 \(About the Language Reference\)
2 |
3 | 문법 사용의 표기법을 읽어봅니다.
4 |
5 | 책의 이 부분은 Swift 프로그래밍 언어의 일반적인 문법을 설명합니다. 여기서 설명한 문법은 파서 또는 컴파일러를 직접 구현하는 것보다 언어를 더 자세히 이해하는데 도움을 주기 위한 것입니다.
6 |
7 | Swift 의 코드의 거의 모든 곳에 나타나는 많은 공통 타입, 함수, 그리고 연산자가 실제로 Swift 표준 라이브러리에 정의되어 있으므로 Swift 언어는 상대적으로 작습니다. 이러한 타입, 함수, 그리고 연산자는 Swift 언어 자체의 부분은 아니지만 책의 부분에서 의견 및 코드 예제에서 광범위하게 사용됩니다.
8 |
9 | ## 문법을 읽는 방법 \(How to Read the Grammar\)
10 |
11 | Swift 프로그래밍 언어의 일반적인 문법을 설명하는데 사용되는 표기법은 몇가지 규칙을 따릅니다:
12 |
13 | * 화살표 \(→\)는 문법 제작을 표시하는데 사용되며 "구성될 수 있음" 으로 읽을 수 있습니다.
14 | * 구문 카테고리는 _기울임꼴_ 텍스트로 표시되고 문법 생성 규칙의 양쪽에 나타납니다.
15 | * 리터럴 단어와 구두점은 굵게 `constant width` 텍스트로 표시되고 문법 제작 규칙의 오른쪽에만 나타납니다.
16 | * 대체 문법 제작은 세로 막대로 \(\|\)로 구분됩니다. 대체 문법이 너무 길어서 쉽게 읽을 수 없을 경우 새 줄에 여러 문법 제작 규칙으로 나뉩니다.
17 | * 경우에 따라 일반 글꼴 텍스트가 문법 생성 규칙의 오른쪽을 설명하는데 사용됩니다.
18 | * 옵셔널 구문 카테고리와 리터럴은 후행 물음표인 _?_ 로 표시됩니다.
19 |
20 | 예를 들어, getter-setter 블럭의 문법은 다음과 같이 정의됩니다:
21 |
22 | > Grammar of a getter-setter block:
23 | >
24 | > *getter-setter-block* → **`{`** *getter-clause* *setter-clause*_?_ **`}`** | **`{`** *setter-clause* *getter-clause* **`}`**
25 |
26 | 이 정의는 getter-setter 블럭이 중괄호로 묶인 옵셔널 setter 절이 뒤따르는 getter 절 또는 중괄호로 묶인 getter 절이 뒤따르는 setter 절로 구성될 수 있음을 나타냅니다. 위의 문법 생성은 다음 두가지 생성과 동일하며 대안이 명시적으로 설명되어 있습니다:
27 |
28 | > Grammar of a getter-setter block:
29 | >
30 | >
31 | > *getter-setter-block* → **`{`** *getter-clause* *setter-clause*_?_ **`}`** \
32 | > *getter-setter-block* → **`{`** *setter-clause* *getter-clause* **`}`**
33 |
34 |
--------------------------------------------------------------------------------
/language-reference/generic-parameters-and-arguments.md:
--------------------------------------------------------------------------------
1 | # 제너릭 파라미터와 인수 (Generic Parameters and Arguments)
2 |
3 | 선언을 일반화하여 구체적인 타입을 추상화합니다.
4 |
5 | 이 챕터에서 제너릭 타입, 함수, 그리고 초기화 구문에 대한 파라미터와 인수를 설명합니다. 제너릭 타입, 함수, 서브 스크립트, 또는 초기화 구문을 선언할 때 제너릭 타입, 함수, 또는 초기화 구문이 동작할 수 있는 타입 파라미터를 지정합니다. 이러한 타입 파라미터는 제너릭 타입의 인스턴스가 생성되거나 제너릭 함수 또는 초기화 구문이 호출 될 때 실제 구체적인 타입 인수에 의해 대체되는 자리표시자 역할을 합니다.
6 |
7 | Swift 의 제너릭에 대한 개요는 [제너릭 (Generics)](../language-guide-1/generics.md) 을 참고 바랍니다.
8 |
9 | ## 제너릭 파라미터 절 (Generic Parameter Clause)
10 |
11 | _제너릭 파라미터 절 (generic parameter clause)_ 은 해당 파라미터의 관련된 모든 제약조건과 요구사항과 함께 제너릭 타입 또는 함수의 타입 파라미터를 지정합니다. 제너릭 파라미터 절은 꺾쇠 괄호 (<>) 로 둘러싸여 있고 다음의 형식을 가집니다:
12 |
13 | ```swift
14 | <<#generic parameter list#>>
15 | ```
16 |
17 | _제너릭 파라미터 리스트 (generic parameter list)_ 는 콤마로 구분된 제너릭 파라미터의 리스트고 각각 다음의 형식을 가집니다:
18 |
19 | ```swift
20 | <#type parameter#>: <#constraint#>
21 | ```
22 |
23 | 제너릭 파라미터는 _타입 파라미터 (type parameter)_ 와 옵셔널 _제약사항 (constraint)_ 으로 구성됩니다. _타입 파라미터 (type parameter)_ 는 자리표시자 타입의 간단한 이름입니다 (예를 들어 `T`, `U`, `V`, `Key`, `Value`, 등). 함수 또는 초기화 구문의 시그니처를 포함하는 나머지 타입, 함수, 또는 초기화 구문 선언에서 타입 파라미터와 모든 연관된 타입에 접근할 수 있습니다.
24 |
25 | _제약조건 (constraint)_ 은 타입 파라미터가 특정 클래스를 상속하거나 프로토콜 또는 프로토콜 구성을 준수하도록 지정합니다. 예를 들어 아래 제너릭 함수에서 제너릭 파라미터 `T: Comparable` 은 타입 파라미터 `T` 를 대신하는 모든 타입 인수는 `Comparable` 프로토콜을 준수해야 함을 나타냅니다.
26 |
27 | ```swift
28 | func simpleMax(_ x: T, _ y: T) -> T {
29 | if x < y {
30 | return y
31 | }
32 | return x
33 | }
34 | ```
35 |
36 | 예를 들어 `Int` 와 `Double` 은 `Comparable` 프로토콜을 준수하므로 이 함수는 두 타입의 인수를 허용합니다. 제너릭 타입과 다르게 제너릭 함수 또는 초기화 구문을 사용할 때 제너릭 인수 절을 지정하지 않습니다. 대신에 타입 인수는 함수나 초기화 구문에 전달되는 인수의 타입으로 부터 추론됩니다.
37 |
38 | ```swift
39 | simpleMax(17, 42) // T is inferred to be Int
40 | simpleMax(3.14159, 2.71828) // T is inferred to be Double
41 | ```
42 |
43 | ### 제너릭 Where 절 (Generic Where Clauses)
44 |
45 | 타입이나 함수의 본문에 열린 괄호 직전에 제너릭 `where` 절을 포함하여 타입 파라미터와 연관된 타입의 요구사항을 추가로 지정할 수 있습니다. 제너릭 `where` 절은 `where` 키워드 다음에 콤마로 구분된 하나 이상의 _요구사항 (requirements)_ 으로 구성됩니다.
46 |
47 | ```swift
48 | where <#requirements#>
49 | ```
50 |
51 | 제너릭 `where` 절에서 _요구사항 (requirements)_ 은 클래스를 상속하거나 프로토콜 또는 프로토콜 구성을 준수하는 타입 파라미터를 지정합니다. 제너릭 `where` 절은 예를 들어 `` 은 ` where T: Comparable` 과 동일하듯 타입 파라미터에 제약사항을 간단하게 표현하는 구문 설탕을 제공하지만 타입 파라미터와 연관된 타입에 더 복잡한 제약사항을 제공하기 위해 사용할 수 있습니다. 예를 들어 프로토콜을 준수하도록 타입 파라미터의 연관된 타입을 제한할 수 있습니다. 예를 들어 ` where S.Iterator.Element: Equatable` 은 `S` 가 `Sequence` 프로토콜을 준수하고 연관된 타입 `S.Iterator.Element` 는 `Equatable` 프로토콜을 준수하도록 지정합니다. 이 제약사항은 시퀀스의 각 요소는 동등함을 보장합니다.
52 |
53 | `==` 연산자를 사용하여 두 타입이 동일해야 하는 요구사항을 지정할 수도 있습니다. 예를 들어 ` where S1.Iterator.Element == S2.Iterator.Element` 은 `S1` 과 `S2` 가 `Sequence` 프로토콜을 준수하고 두 시퀀스의 요소는 같은 타입이어야 한다는 제약사항이 있습니다.
54 |
55 | 타입 파라미터를 대체하는 모든 타입 인수는 타입 파라미터에 있는 모든 제약사항과 요구사항을 만족해야 합니다.
56 |
57 | 제너릭 `where` 절은 타입 파라미터를 포함하는 선언의 부분 또는 타입 파라미터를 포함하는 선언의 내부에 중첩된 선언의 부분으로 나타날 수 있습니다. 중첩된 선언에 대한 제너릭 `where` 절은 둘러싸는 선언의 타입 파라미터를 참조할 수 있습니다; 그러나 `where` 절의 요구사항은 작성된 선언에만 적용됩니다.
58 |
59 | 둘러싸는 선언도 `where` 절을 가지고 있으면 두 절의 요구사항은 결합됩니다. 아래 예제에서 `startsWithZero()` 는 `Element` 가 `SomeProtocol` 과 `Numeric` 모두 준수하는 경우에만 가능합니다.
60 |
61 | ```swift
62 | extension Collection where Element: SomeProtocol {
63 | func startsWithZero() -> Bool where Element: Numeric {
64 | return first == .zero
65 | }
66 | }
67 | ```
68 |
69 | 타입 파라미터에 다른 제약조건, 요구사항, 또는 둘 다 제공하여 제너릭 함수 또는 초기화 구문을 오버로드 할 수 있습니다. 오버로드 된 제너릭 함수 또는 초기화 구문을 호출할 때 컴파일러는 호출할 오버로드 된 함수 또는 초기화 구문을 확인하기 위해 이 제약조건을 사용합니다.
70 |
71 | 제너릭 `where` 절에 대한 자세한 정보와 제너릭 함수 선언의 예제를 보려면 [제너릭 Where 절 (Generic Where Clauses)](../language-guide-1/generics.md#where-generic-where-clauses) 을 참고 바랍니다.
72 |
73 | > Grammar of a generic parameter clause:
74 | >
75 | > *generic-parameter-clause* → **`<`** *generic-parameter-list* **`>`** \
76 | > *generic-parameter-list* → *generic-parameter* | *generic-parameter* **`,`** *generic-parameter-list* \
77 | > *generic-parameter* → *type-name* \
78 | > *generic-parameter* → *type-name* **`:`** *type-identifier* \
79 | > *generic-parameter* → *type-name* **`:`** *protocol-composition-type*
80 | >
81 | > *generic-where-clause* → **`where`** *requirement-list* \
82 | > *requirement-list* → *requirement* | *requirement* **`,`** *requirement-list* \
83 | > *requirement* → *conformance-requirement* | *same-type-requirement*
84 | >
85 | > *conformance-requirement* → *type-identifier* **`:`** *type-identifier* \
86 | > *conformance-requirement* → *type-identifier* **`:`** *protocol-composition-type* \
87 | > *same-type-requirement* → *type-identifier* **`==`** *type*
88 |
89 | ## 제너릭 인수 절 (Generic Argument Clause)
90 |
91 | _제너릭 인수 절 (generic argument clause)_ 은 제너릭 타입의 타입 인수를 지정합니다. 제너릭 인수 절은 꺾쇠 괄호 (<>) 로 둘러싸여져 있고 다음의 형식을 가집니다:
92 |
93 | ```swift
94 | <<#generic argument list#>>
95 | ```
96 |
97 | _제너릭 인수 리스트 (generic argument list)_ 는 콤마로 구분된 타입 인수의 리스트입니다. _타입 인수 (type argument)_ 는 제너릭 타입의 제너릭 파라미터 절에서 해당 타입 파라미터를 대체하는 실제 구체적인 타입의 이름입니다. 결과는 해당 제너릭 타입의 특수 버전입니다. 아래 예제는 Swift 표준 라이브러리의 제너릭 딕셔너리 타입의 간단한 버전을 보여줍니다.
98 |
99 | ```swift
100 | struct Dictionary: Collection, ExpressibleByDictionaryLiteral {
101 | /* ... */
102 | }
103 | ```
104 |
105 | 제너릭 `Dictionary` 타입의 특수한 버전인 `Dictionary` 는 제너릭 파라미터 `Key: Hashable` 과 `Value` 를 구체적인 타입 인수 `String` 과 `Int` 로 대체하여 구성됩니다. 각 타입 인수는 제너릭 `where` 절에 지정된 추가 요구사항을 포함하여 대체하는 제너릭 파라미터의 모든 제약사항을 충족해야 합니다. 위의 예제에서 `Key` 타입 파라미터는 `Hashable` 프로토콜을 준수하도록 제한되므로 `String` 도 `Hashable` 프로토콜을 준수해야 합니다.
106 |
107 | 타입 파라미터를 적절한 제약사항과 요구사항을 충족하는 경우 그 자체가 제너릭 타입의 특별한 버전인 타입 인수로 대체할 수 있습니다. 예를 들어 요소 자체가 정수의 배열인 `Array` 은 `Array` 배열의 특별한 버전으로 타입 파라미터 `Element` 를 대체할 수 있습니다.
108 |
109 | ```swift
110 | let arrayOfArrays: Array> = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
111 | ```
112 |
113 | [제너릭 파라미터 절 (Generic Parameter Clause)](generic-parameters-and-arguments.md#generic-parameter-clause) 에서 언급했듯이 제너릭 함수 또는 초기화 구문의 타입 인수로 지정하기 위해 제너릭 인수 절을 사용하지 않습니다.
114 |
115 | > Grammar of a generic argument clause:
116 | >
117 | > *generic-argument-clause* → **`<`** *generic-argument-list* **`>`** \
118 | > *generic-argument-list* → *generic-argument* | *generic-argument* **`,`** *generic-argument-list* \
119 | > *generic-argument* → *type*
120 |
--------------------------------------------------------------------------------
/language-reference/patterns.md:
--------------------------------------------------------------------------------
1 | # 패턴 (Patterns)
2 |
3 | 값을 일치시키고 분리합니다.
4 |
5 | _패턴 (pattern)_ 은 단일 값 또는 복합 값의 구조를 나타냅니다. 예를 들어 튜플 `(1, 2)` 의 구조는 콤마로 구분된 두 요소의 리스트입니다. 패턴은 특정값이 아닌 값의 구조를 나타내기 때문에 다양한 값과 일치 시킬 수 있습니다. 예를 들어 패턴 `(x, y)` 은 튜플 `(1, 2)` 와 다른 두 요소 튜플과 일치합니다. 패턴을 값과 일치시키는 것 외에도 복합 값의 일부 또는 전체를 추출하고 각 부분을 상수 또는 변수 이름으로 바인드 할 수 있습니다.
6 |
7 | Swift 에는 두가지의 기본 패턴이 있습니다: 모든 종류의 값과 일치하는 패턴과 런타임에 지정된 값과 일치하지 않을 수 있는 패턴이 있습니다.
8 |
9 | 패턴의 첫번째 종류는 단순 변수, 상수, 그리고 옵셔널 바인딩에서 값을 구조화 하는데 사용됩니다. 와일드 카드 패턴, 식별자 패턴, 그리고 이를 포함하는 모든 값 바인딩 또는 튜플 패턴이 포함됩니다. 이러한 패턴에 타입 주석을 지정하여 특정 타입의 값만 일치되도록 제한할 수 있습니다.
10 |
11 | 패턴의 두번째 종류는 전체 패턴 일치에 사용되며 일치하려는 값이 런타임 때 없을 수 있습니다. 열거형 케이스 패턴, 옵셔널 패턴, 표현식 패턴, 그리고 타입-캐스팅 패턴을 포함합니다. `switch` 구문의 케이스 라벨, `do` 구문의 `catch` 절, 또는 `if`, `while`, `guard`, 또는 `for`-`in` 구문의 케이스 조건에서 이 패턴을 사용합니다.
12 |
13 | > Grammar of a pattern:
14 | >
15 | > *pattern* → *wildcard-pattern* *type-annotation*_?_ \
16 | > *pattern* → *identifier-pattern* *type-annotation*_?_ \
17 | > *pattern* → *value-binding-pattern* \
18 | > *pattern* → *tuple-pattern* *type-annotation*_?_ \
19 | > *pattern* → *enum-case-pattern* \
20 | > *pattern* → *optional-pattern* \
21 | > *pattern* → *type-casting-pattern* \
22 | > *pattern* → *expression-pattern*
23 |
24 | ## 와일드 카드 패턴 (Wildcard Pattern)
25 |
26 | _와일드 카드 패턴 (wildcard pattern)_ 은 모든 값과 일치하고 무시되며 언더바 (`_`) 로 구성됩니다. 일치하는 값에 대해 신경쓰지 않을 경우에 와일드 카드 패턴을 사용합니다. 예를 들어 다음의 코드는 닫힌 범위 `1...3` 을 반복하고 루프가 반복할 때마다 범위의 현재값을 무시합니다:
27 |
28 | ```swift
29 | for _ in 1...3 {
30 | // Do something three times.
31 | }
32 | ```
33 |
34 | > Grammar of a wildcard pattern:
35 | >
36 | > *wildcard-pattern* → **`_`**
37 |
38 | ## 식별자 패턴 (Identifier Pattern)
39 |
40 | _식별자 패턴 (identifier pattern)_ 은 모든 값과 일치하고 일치하는 값을 변수 또는 상수 이름으로 바인드 합니다. 예를 들어 다음의 상수 선언에서 `someValue` 는 타입 `Int` 의 `42` 값이 일치하는 식별자 패턴입니다:
41 |
42 | ```swift
43 | let someValue = 42
44 | ```
45 |
46 | 일치가 성공하면 값 `42` 는 상수 이름 `someValue` 에 바인드 (할당) 됩니다.
47 |
48 | 변수 또는 상수 선언의 왼쪽의 패턴이 식별자 패턴일 때 식별자 패턴은 암시적으로 값-바인딩 패턴 (value-binding pattern) 의 하위 패턴입니다.
49 |
50 | > Grammar of an identifier pattern:
51 | >
52 | > *identifier-pattern* → *identifier*
53 |
54 | ## 값-바인딩 패턴 (Value-Binding Pattern)
55 |
56 | _값-바인딩 패턴 (value-binding pattern)_ 은 변수 또는 상수 이름에 일치되는 값으로 바인드 합니다. 상수의 이름에 일치되는 값을 바인드 하는 값-바인딩 패턴은 `let` 키워드로 시작합니다; 변수의 이름에 바인드 하면 `var` 키워드로 시작합니다.
57 |
58 | 값-바인딩 패턴 내에서 식별자 패턴은 일치하는 값으로 새로운 명명된 변수 또는 상수로 바인드 됩니다. 예를 들어 튜플의 요소를 분해하고 각 요소의 값을 해당 식별자 패턴에 바인드 할 수 있습니다.
59 |
60 | ```swift
61 | let point = (3, 2)
62 | switch point {
63 | // Bind x and y to the elements of point.
64 | case let (x, y):
65 | print("The point is at (\(x), \(y)).")
66 | }
67 | // Prints "The point is at (3, 2)."
68 | ```
69 |
70 | 위의 예제에서 `let` 은 튜플 패턴 `(x, y)` 에서 각 식별자 패턴에 배포합니다. 이 동작으로 인해 `switch` 케이스 `case let (x, y):` 와 `case (let x, let y):` 은 동일합니다.
71 |
72 | > Grammar of a value-binding pattern:
73 | >
74 | > *value-binding-pattern* → **`var`** *pattern* | **`let`** *pattern*
75 |
76 | ## 튜플 패턴 (Tuple Pattern)
77 |
78 | _튜플 패턴 (tuple pattern)_ 은 소괄호로 묶인 콤마로 구분된 0개 이상의 패턴의 리스트입니다. 튜플 패턴은 해당 튜플 타입의 값과 일치합니다.
79 |
80 | 타입 주석을 사용하여 튜플 타입의 특정 종류와 일치하도록 하기 위해 튜플 패턴을 제한할 수 있습니다. 예를 들어 상수 선언 `let (x, y): (Int, Int) = (1, 2)` 에서 튜플 패턴 `(x, y): (Int, Int)` 은 두 요소 모두 타입 `Int` 의 튜플 타입만 일치합니다.
81 |
82 | 튜플 패턴이 `for`-`in` 구문 또는 변수 또는 상수 선언에서 패턴으로 사용되면 와일드 카드 패턴, 식별자 패턴, 옵셔널 패턴, 또는 이를 포함하는 다른 튜플 패턴만 포함할 수 있습니다. 예를 들어 튜플 패턴 `(x, 0)` 에서 요소 `0` 은 표현식 패턴이므로 다음의 코드는 유효하지 않습니다:
83 |
84 | ```swift
85 | let points = [(0, 0), (1, 0), (1, 1), (2, 0), (2, 1)]
86 | // This code isn't valid.
87 | for (x, 0) in points {
88 | /* ... */
89 | }
90 | ```
91 |
92 | 단일 요소를 포함하는 튜플 패턴 주변의 소괄호는 아무런 효과가 없습니다. 패턴은 단일 요소의 타입의 값과 일치합니다. 예를 들어 다음은 동일합니다:
93 |
94 | ```swift
95 | let a = 2 // a: Int = 2
96 | let (a) = 2 // a: Int = 2
97 | let (a): Int = 2 // a: Int = 2
98 | ```
99 |
100 | > Grammar of a tuple pattern:
101 | >
102 | > *tuple-pattern* → **`(`** *tuple-pattern-element-list*_?_ **`)`** \
103 | > *tuple-pattern-element-list* → *tuple-pattern-element* | *tuple-pattern-element* **`,`** *tuple-pattern-element-list* \
104 | > *tuple-pattern-element* → *pattern* | *identifier* **`:`** *pattern*
105 |
106 | ## 열거형 케이스 패턴 (Enumeration Case Pattern)
107 |
108 | _열거형 케이스 패턴 (enumeration case pattern)_ 은 존재하는 열거형 타입의 케이스와 일치합니다. 열거형 케이스 패턴은 `switch` 구문 케이스 라벨과 `if`, `while`, `guard`, 그리고 `for`-`in` 구문의 케이스 조건에서 나타납니다.
109 |
110 | 일치 시키려는 열거형 케이스에 연관된 값이 있는 경우 해당 열거형 케이스 패턴은 각 연관된 값에 대한 하나의 요소를 포함하는 튜플 패턴을 지정해야 합니다. 연관된 값을 포함하는 열거형 케이스를 일치 시키기 위해 `switch` 구문을 사용하는 예제는 [연관된 값 (Associated Values)](../language-guide-1/enumerations.md#associated-values) 을 참고 바랍니다.
111 |
112 | 열거형 케이스 패턴은 옵셔널로 래핑된 케이스의 값과도 일치합니다. 이 간략한 구문으로 옵셔널 패턴을 생략할 수 있습니다. `Optional` 은 열거형으로 구현되므로 `.none` 과 `.some` 은 열거형 타입의 케이스로 동일한 switch 에 나타날 수 있습니다.
113 |
114 | ```swift
115 | enum SomeEnum { case left, right }
116 | let x: SomeEnum? = .left
117 | switch x {
118 | case .left:
119 | print("Turn left")
120 | case .right:
121 | print("Turn right")
122 | case nil:
123 | print("Keep going straight")
124 | }
125 | // Prints "Turn left"
126 | ```
127 |
128 | > Grammar of an enumeration case pattern:
129 | >
130 | > *enum-case-pattern* → *type-identifier*_?_ **`.`** *enum-case-name* *tuple-pattern*_?_
131 |
132 | ## 옵셔널 패턴 (Optional Pattern)
133 |
134 | _옵셔널 패턴 (optional pattern)_ 은 `Optional` 열거형의 `some(Wrapped)` 케이스에 래핑된 값과 일치합니다. 옵셔널 패턴은 식별자 패턴과 물음표 바로 뒤에 오는 것으로 구성되며 열거형 케이스 패턴과 동일한 위치에 나타납니다.
135 |
136 | 옵셔널 패턴은 `Optional` 열거형 케이스 패턴에 대한 구문 설탕 이므로 다음은 동일합니다:
137 |
138 | ```swift
139 | let someOptional: Int? = 42
140 | // Match using an enumeration case pattern.
141 | if case .some(let x) = someOptional {
142 | print(x)
143 | }
144 |
145 | // Match using an optional pattern.
146 | if case let x? = someOptional {
147 | print(x)
148 | }
149 | ```
150 |
151 | 옵셔널 패턴은 `for`-`in` 구문에서 옵셔널 값의 배열을 반복하는 편리한 방법을 제공하여 `nil` 이 아닌 요소에 대해서만 루프의 본문을 실행합니다.
152 |
153 | ```swift
154 | let arrayOfOptionalInts: [Int?] = [nil, 2, 3, nil, 5]
155 | // Match only non-nil values.
156 | for case let number? in arrayOfOptionalInts {
157 | print("Found a \(number)")
158 | }
159 | // Found a 2
160 | // Found a 3
161 | // Found a 5
162 | ```
163 |
164 | > Grammar of an optional pattern:
165 | >
166 | > *optional-pattern* → *identifier-pattern* **`?`**
167 |
168 | ## 타입-캐스팅 패턴 (Type-Casting Patterns)
169 |
170 | 타입-캐스팅 패턴 (type-casting pattern) 은 `is` 패턴과 `as` 패턴 두가지가 있습니다. `is` 패턴은 `switch` 구문 케이스 라벨에서만 나타납니다. `is` 와 `as` 패턴은 다음의 형식을 가집니다:
171 |
172 | ```swift
173 | is <#type#>
174 | <#pattern#> as <#type#>
175 | ```
176 |
177 | `is` 패턴은 런타임 시 해당 값의 타입이 `is` 패턴의 오른편에 지정한 타입과 일치하거나 해당 타입의 하위 클래스가 일치하면 값으로 일치됩니다. `is` 패턴은 타입 캐스트를 동작하지만 반환된 타입을 버린다는 것에서 `is` 연산자와 유사하게 동작합니다.
178 |
179 | `as` 패턴은 런타임 시 해당 값의 타입이 `as` 패턴의 오른편에 지정한 타입과 일치하거나 해당 타입의 하위 클래스가 일치하면 값으로 일치합니다. 일치가 성공하면 일치된 값의 타입은 `as` 패턴의 오른편에 지정한 _패턴 (pattern)_ 으로 캐스팅 됩니다.
180 |
181 | `is` 와 `as` 패턴으로 값을 일치 시키기 위해 `switch` 구문을 사용하는 예제는 [Any 와 AnyObject 에 대한 타입 캐스팅 (Type Casting for Any and AnyObject)](../language-guide-1/type-casting.md#any-anyobject-type-casting-for-any-and-anyobject) 을 참고 바랍니다.
182 |
183 | > Grammar of a type casting pattern:
184 | >
185 | > *type-casting-pattern* → *is-pattern* | *as-pattern* \
186 | > *is-pattern* → **`is`** *type* \
187 | > *as-pattern* → *pattern* **`as`** *type*
188 |
189 | ## 표현식 패턴 (Expression Pattern)
190 |
191 | _표현식 패턴 (expression pattern)_ 은 표현식의 값을 표현합니다. 표현식 패턴은 `switch` 구문 케이스 라벨에서만 나타납니다.
192 |
193 | 표현식 패턴에 의해 표현된 표현식은
194 | Swift 표준 라이브러리의 패턴 일치 연산자 (`~=`) 를 사용하여 입력 표현식의 값과 비교합니다.
195 | `~=` 연산자가 `true` 를 반환하면 일치는 성공합니다.
196 | 기본적으로 `~=` 연산자는 `==` 연산자를 사용하여 동일한 타입의 두 값을 비교합니다.
197 | 다음 예제에서 보듯이 범위내에 값이 포함되는지 검사하기 위해 값의 범위로 값을 일치시킬 수도 있습니다.
198 |
199 | ```swift
200 | let point = (1, 2)
201 | switch point {
202 | case (0, 0):
203 | print("(0, 0) is at the origin.")
204 | case (-2...2, -2...2):
205 | print("(\(point.0), \(point.1)) is near the origin.")
206 | default:
207 | print("The point is at (\(point.0), \(point.1)).")
208 | }
209 | // Prints "(1, 2) is near the origin."
210 | ```
211 |
212 | 사용자 정의 표현식 일치 동작을 제공하기 위해 `~=` 연산자를 오버로드 할 수 있습니다. 예를 들어 포인트의 문자열 표현으로 `point` 표현식을 비교하기 위해 위의 예제를 다시 작성할 수 있습니다.
213 |
214 | ```swift
215 | // Overload the ~= operator to match a string with an integer.
216 | func ~= (pattern: String, value: Int) -> Bool {
217 | return pattern == "\(value)"
218 | }
219 | switch point {
220 | case ("0", "0"):
221 | print("(0, 0) is at the origin.")
222 | default:
223 | print("The point is at (\(point.0), \(point.1)).")
224 | }
225 | // Prints "The point is at (1, 2)."
226 | ```
227 |
228 | > Grammar of an expression pattern:
229 | >
230 | > *expression-pattern* → *expression*
231 |
--------------------------------------------------------------------------------
/revision-history/document-revision-history.md:
--------------------------------------------------------------------------------
1 | # Document Revision History
2 |
3 | ## Revision History
4 |
5 | ### 2025-04-02(수)
6 |
7 | - Swift 6.1 기반으로 문서 업데이트.
8 | - [불투명한 파라미터 타입 (Opaque Parameter Types)](../language-guide-1/opaque-types.md#불투명한-파라미터-타입-opaque-parameter-types) 섹션을 추가하여
9 | `some`을 제너릭의 간단한 문법으로 사용하는 방법에 대한 정보를 포함.
10 | - [available](../language-reference/attributes.md#available) 섹션에
11 | `noasync` 인수에 대한 정보를 추가.
12 |
13 | ### 2024-09-19(목)
14 |
15 | - Swift 6 기반으로 문서 업데이트.
16 | - 오탈자 수정.
17 |
18 | ### 2024-07-02(화)
19 |
20 | - Swift 6 Beta 기반으로 문서 업데이트.
21 | - 엄격한 동시성 검사로 변환을 위한 정보를
22 | [preconcurrency](../language-reference/attributes.md#preconcurrency) 섹션에 추가.
23 | - 특정 타입의 에러 발생에 대한 내용을
24 | [에러 타입 지정 (Specifying the Error Type)](../language-guide-1/error-handling.md#에러-타입-지정-specifying-the-error-type) 섹션에 추가.
25 | - [접근 제어 (Access Control)](../language-guide-1/access-control.md) 챕터에
26 | 패키지-수준 접근에 대한 내용 추가.
27 |
28 | ### 2024-03-08(금)
29 |
30 | - Swift 5.10 기반으로 문서 작업
31 | - 오탈자 수정
32 |
33 | ### 2024-02-25(일)
34 |
35 | - Swift 5.10 Beta 기반으로 문서 작업
36 | - 중첩된 프로토콜에 대한 내용을
37 | [위임 (Delegation)](../language-guide-1/protocols.md#위임-delegation) 섹션에 추가.
38 | - [UIApplicationMain](../language-reference/attributes.md#uiapplicationmain) 과
39 | [NSApplicationMain](../language-reference/attributes.md#nsapplicationmain) 섹션에
40 | 더이상 사용하지 않는 정보 추가.
41 |
42 | ### 2023-12-12(화)
43 |
44 | - Swift 5.9.2 기반으로 문서 작업
45 | - 작업 (task), 작업 그룹 (task group), 그리고 작업 취소 (task cancellation) 에
46 | 대한 내용을 [동시성 (Concurrency)](../language-guide-1/concurrency.md) 에 추가했습니다.
47 | - 기존 Swift Package 에 매크로 구현에 대한 내용을
48 | [매크로 (Macros)](../language-guide-1/macros.md) 에 추가했습니다.
49 | - Conformance 매크로를 대신해 Extension 매크로에 대한 내용을
50 | [attached](../language-reference/attributes.md#attached) 에 업데이트 했습니다.
51 |
52 | ### 2023-12-03(일)
53 |
54 | - Swift 5.9.2 Beta 기반으로 문서 작업
55 | - `borrowing` 과 `consuming` 수식어에 대한 정보를
56 | [파라미터 수식어 (Parameter Modifiers)](../language-reference/declarations.md#파라미터-수식어-parameter-modifiers) 섹션에 추가했습니다.
57 | - [상수와 변수 선언 \(Declaring Constants and Variables\)](../language-guide-1/the-basics.md#상수와-변수-선언-declaring-constants-and-variables) 에
58 | 상수를 선언한 후에 값을 설정에 대한 정보를 추가했습니다.
59 | - 백 배포 (back deployment) 에 대한 정보를
60 | [backDeployed](../language-reference/attributes.md#backdeployed) 섹션에 추가했습니다.
61 |
62 | ### 2023-09-30(토)
63 |
64 | - Swift 5.9 기반으로 문서 작업
65 | - [기본 (The Basics)](../language-guide-1/the-basics.md) 에 옵셔널에 대한 내용을 추가
66 | - [Swift 둘러보기 (A Swift Tour)](../welcome-to-swift/swift-a-swift-tour.md) 에 동시성 예제 추가
67 | - [결과 변환 (Result Transformations)](../language-reference/attributes.md#결과-변환-result-transformations) 섹션에
68 | `buildPartialBlock(first:)` 와 `buildPartialBlock(accumulated:next:)` 메서드에 대한 내용 추가
69 | - [available](../language-reference/attributes.md#available) 과 [조건부 컴파일 블럭 (Conditional Compilation Block)](../language-reference/statements.md#조건부-컴파일-블럭-conditional-compilation-block) 에서
70 | 플랫폼 목록에 visionOS 추가
71 |
72 | ### 2023-06-19(월)
73 |
74 | * Swift 5.9 Beta 기반으로 문서 작업
75 | * [제어 흐름 \(Control Flow\)](../language-guide-1/control-flow.md) 챕터와 [조건 표현식 (Conditional Expression)](../language-reference/expressions.md#조건-표현식-conditional-expression) 섹션에 `if` 와 `switch` 표현식에 대한 내용을 추가
76 | * 컴파일 때 코드를 생성하는 것에 대한 [매크로 (Macros)](../language-guide-1/macros.md) 챕터 추가
77 | * [불투명한 타입과 박스형 타입 \(Opaque and Boxed Types\)](../language-guide-1/opaque-types.md) 챕터에 박스형 프로토콜 타입 (boxed protocol type) 에 대한 내용을 추가
78 | * `buildPartialBlock(first:)` 와 `buildPartialBlock(accumulated:next:)` 메서드에 대한 내용을 [결과-빌딩 메서드 (Result-Building Methods)](../language-reference/attributes.md#결과-빌딩-메서드-result-building-methods) 섹션에 추가
79 | * Swift-DocC 적용한 [TSPLK (The Swift Programming Language Korean)](https://bbiguduk.github.io/swift-book-korean/documentation/tsplk/) 페이지 오픈
80 | > GitBook 과 Swift-DocC 둘 다 운영할 계획입니다.
81 |
82 | ### 2023-04-04(화)
83 |
84 | * Swift 5.8 기반으로 문서 작업
85 | * 에러 처리 외의 `defer` 를 표시하는 [연기된 동작 (Deferred Actions)](../language-guide-1/control-flow.md#연기된-동작-deferred-actions) 추가
86 | * 오탈자 수정
87 |
88 | ### 2022-09-13(화)
89 |
90 | * Swift 5.7 정식 릴리즈에 따른 오탈자 수정
91 |
92 | ### 2022-06-29(수)
93 |
94 | * 오탈자 수정
95 | * Swift 5.7 기반으로 문서 작업 완료
96 | * 행위자 (actor) 와 작업 (task) 간의 데이터 전송에 대한 내용을 [전송 가능 타입 (Sendable Types)](../language-guide-1/concurrency.md#sendable-types) 섹션에 추가하고 `@Sendable` 과 `@unchecked` 속성에 대한 내용을 [Sendable](../language-reference/attributes.md#sendable) 과 [unchecked](../language-reference/attributes.md#unchecked) 섹션에 추가하였습니다.
97 | * 정규 표현식 생성에 대한 내용을 [정규 표현식 리터럴 (Regular Expression Literals)](../language-reference/lexical-structure.md#regular-expression-literals) 섹션에 추가하였습니다.
98 | * `if`-`let` 형식에 대한 내용을 [옵셔널 바인딩 (Optional Binding)](../language-guide-1/the-basics.md#optional-binding) 섹선에 추가하였습니다.
99 | * `#unavailable` 에 대한 내용을 [사용 가능한 API 확인 (Checking API Availability)](../language-guide-1/control-flow.md#checking-api-availability) 섹션에 추가하였습니다.
100 |
101 | ### 2022-03-17(목)
102 |
103 | * Swift 5.6 정식 릴리즈에 따른 오탈자 수정
104 |
105 | ### 2022-01-29(토)
106 |
107 | * Swift 5.6 기반으로 문서 작업 완료
108 | * 연결된 메서드 호출과 다른 접미사 표현식과 관련된 `#if` 사용에 대한 정보로 [명시적 멤버 표현식 (Explicit Member Expression)](../language-reference/expressions.md#explicit-member-expression) 을 업데이트
109 | * 이미지 파일 업데이트
110 |
111 | ### 2021-10-08(금)
112 |
113 | * [프로퍼티 (Properties)](../language-guide-1/properties.md) 변경 사항 수정
114 | * [동시성 (Concurrency)](../language-guide-1/concurrency.md) 변경 사항 수정
115 |
116 | ### 2021-08-14(토)
117 |
118 | * Swift 5.5 기반으로 문서 작업 완료
119 | * [동시성 (Concurrency)](../language-guide-1/concurrency.md) 추가
120 | * 오탈자 수정
121 |
122 | ### 2021-04-10(토)
123 |
124 | * WELCOME TO SWIFT 번역 완료
125 | * LANGUAGE REFERENCE 번역 완료
126 |
127 | ### 2021-02-20(토)
128 |
129 | * Swift 5.4 기반으로 문서 작업 완료
130 |
131 | ### 2020-10-23(금)
132 |
133 | * Swift 5.3 기반으로 문서 작업 완료
134 |
--------------------------------------------------------------------------------
/welcome-to-swift/swift-about-swift.md:
--------------------------------------------------------------------------------
1 | # Swift 에 대해 \(About Swift\)
2 |
3 | 언어의 높은 수준의 목표를 이해합니다.
4 |
5 | Swift 는 폰, 태블릿, 데스크탑, 서버
6 | 또는 코드를 실행할 수 있는 모든 곳에서
7 | 작성하는 환상적인 소프트웨어입니다.
8 | 현대 언어 사고방식과 오픈소스 커뮤니티의 지혜를 결합한
9 | 안전하고 빠른 프로그래밍 언어입니다.
10 |
11 | Swift 는 숙련된 프로그래머에게
12 | 필요한 성능과 유연성을 놓치지 않으면서
13 | 새로운 프로그래머에게 친숙합니다.
14 | 스크립팅 언어처럼 표현력이 풍부하고
15 | 즐거움이 가득한 프로그래밍 언어입니다.
16 | 컴파일러는 성능에 최적화 되어있고
17 | 언어는 개발에 최적화 되어있으며,
18 | 어느쪽도 타협하지 않습니다.
19 |
20 | Swift 는 최신 프로그래밍 패턴을 채택하여 많은 클래스의 일반적인 프로그래밍 오류를 정의합니다:
21 |
22 | * 변수는 항상 사용 전에 초기화 되어야 합니다.
23 | * 배열 (Array) 인덱스는 범위 초과 \(out-of-bounds\) 에러에 대해 검사되어야 합니다.
24 | * 정수 \(Integer\)는 오버플로우 \(overflow\)에 대해 검사되어야 합니다.
25 | * 옵셔널 \(Optional\)은 `nil` 값이 명시적으로 처리되도록 합니다.
26 | * 메모리는 자동으로 관리됩니다.
27 | * 에러 처리를 통해 예기치 않은 오류를 처리할 수 있습니다.
28 |
29 | Swift 코드는 최신 하드웨어를 최대한 활용하기 위해 컴파일되고 최적화 됩니다.
30 | 구문과 표준 라이브러리는 코드를 작성하는 방법이
31 | 최상의 성능을 발휘해야 한다는 기본원칙에 따라 설계되었습니다.
32 | 안전성과 속도의 조합으로 Swift 는 "Hello, world!" 로 부터 전체 시스템에 이르기 까지 최고의 선택입니다.
33 |
34 | Swift 는 강력한 기능으로 타입 추론 (type inference) 과 패턴 매칭 (pattern matching) 을
35 | 다른 유명한 언어를 개발하는 개발자들에게 친숙한
36 | 현대적이고 가벼운 구문으로 결합하여
37 | 복잡한 것도 명확하고 간결한 방식으로 표현할 수 있습니다.
38 | 그 결과로 코드는 읽고, 쓰고, 유지하기 쉽습니다.
39 |
40 | Swift 는 새롭고 강력한 기능으로 발전하고 있습니다.
41 | Swift 에 대한 목표는 야심찹니다.
42 | Swift 로 무엇을 만들지 기대가 됩니다.
43 |
44 |
--------------------------------------------------------------------------------
/welcome-to-swift/version-compatibility.md:
--------------------------------------------------------------------------------
1 | # 버전 호환성 \(Version Compatibility\)
2 |
3 | 이전 언어 모드에서 사용가능한 기능에 대해 배웁니다.
4 |
5 | 이 책은 Xcode 16.3 에 포함된 Swift 의 기본 버전인,
6 | Swift 6.1 에 대해 설명합니다.
7 | Swift 6.1, Swift 5, Swift 4.2, 또는 Swift 4 로 작성된
8 | 코드를 빌드하기위해 Swift 6.1 컴파일러를 사용할 수 있습니다.
9 |
10 | Swift 5 언어 모드를 사용하는 코드를 빌드하기위해
11 | Swift 6.1 컴파일러를 사용하면,
12 | Swift 6.1 의 새로운 기능을 사용할 수 있습니다 ---
13 | 새로운 기능은 기본적으로 활성화 되거나 플래그로 인해 활성화 됩니다.
14 | 그러나, 엄격한 비동기 검사를 활성화 하려면,
15 | Swift 6.1 언어 모드로 업그레이드가 필요합니다.
16 |
17 | 또한,
18 | Swift 4 와 Swift 4.2 코드를 빌드하기위해 Xcode 15.3 을 사용하면,
19 | 대부분의 Swift 5 기능을 사용할 수 있습니다.
20 | 다시 말해,
21 | 다음의 변경사항은 Swift 5 언어 모드를 사용하는
22 | 코드에서만 사용가능 합니다:
23 |
24 | * 불투명한 타입 (opaque type) 을 반환하는 함수는 Swift 5.1 런타임이 필요합니다.
25 | * `try?` 표현식은 이미 옵셔널 (optional) 을 반환하는 표현식에 추가로 옵셔널 표현식을 도입하지 않습니다.
26 | * 큰 정수 (integer) 리터럴 초기화 표현식은 올바른 정수 (integer) 타입으로 추론합니다. 예를 들어 `UInt64(0xffff_ffff_ffff_ffff)` 는 오버플로우가 아닌 올바른 값입니다.
27 |
28 | 동시성 (Concurrency) 은 Swift 5 언어 모드와
29 | 동시성 타입을 제공하는 Swift 표준 라이브러리의 버전이 필요합니다.
30 | 애플 플랫폼에서 배포 대상 (deployment target) 을 적어도
31 | iOS 13, macOS 10.15, tvOS 13, watchOS 6, 또는 visionOS 1 로 설정합니다.
32 |
33 | Swift 6.1 으로 작성된 타겟은
34 | Swift 5, Swift 4.2 또는 Swift 4 로 작성된 타겟에 따라 달리질 수 있으며
35 | 그 반대의 경우도 마찬가지입니다.
36 | 즉, 여러 프레임워크로 분할 된 대규모 프로젝트가 있는 경우
37 | 코드를 새로운 언어 버전으로
38 | 한번에 하나씩 프레임워크로 마이그레이션 할 수 있습니다.
39 |
40 |
--------------------------------------------------------------------------------