From 88d88344bfbb03d2e012ea12a85995d1d5ca07d3 Mon Sep 17 00:00:00 2001 From: Bambu Date: Tue, 6 Jan 2026 16:47:08 +0900 Subject: [PATCH 01/26] =?UTF-8?q?docs:=20gitignore=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ba8673d --- /dev/null +++ b/.gitignore @@ -0,0 +1,67 @@ +.DS_Store +._.DS_Store +**/.DS_Store +**/._.DS_Store + +# Xcode +# +# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore + +## User settings +xcuserdata/ + +## Obj-C/Swift specific +*.hmap + +## App packaging +*.ipa +*.dSYM.zip +*.dSYM + +## Playgrounds +timeline.xctimeline +playground.xcworkspace + +# Swift Package Manager +# +# Add this line if you want to avoid checking in source code from Swift Package Manager dependencies. +# Packages/ +# Package.pins +# Package.resolved +# *.xcodeproj +# +# Xcode automatically generates this directory with a .xcworkspacedata file and xcuserdata +# hence it is not needed unless you have added a package configuration file to your project +# .swiftpm + +.build/ + +# CocoaPods +# +# We recommend against adding the Pods directory to your .gitignore. However +# you should judge for yourself, the pros and cons are mentioned at: +# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control +# +# Pods/ +# +# Add this line if you want to avoid checking in source code from the Xcode workspace +# *.xcworkspace + +# Carthage +# +# Add this line if you want to avoid checking in source code from Carthage dependencies. +# Carthage/Checkouts + +Carthage/Build/ + +# fastlane +# +# It is recommended to not store the screenshots in the git repo. +# Instead, use fastlane to re-generate the screenshots whenever they are needed. +# For more information about the recommended setup visit: +# https://docs.fastlane.tools/best-practices/source-control/#source-control + +fastlane/report.xml +fastlane/Preview.html +fastlane/screenshots/**/*.png +fastlane/test_output From d2c6bc5f54f63366aef559657db67a2ae511746a Mon Sep 17 00:00:00 2001 From: Bambu Date: Tue, 6 Jan 2026 16:53:38 +0900 Subject: [PATCH 02/26] =?UTF-8?q?Docs:=20=EA=B8=B0=EC=A1=B4=20=EC=9E=91?= =?UTF-8?q?=EC=97=85=20=ED=8C=8C=EC=9D=BC=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../README.md" | 2 + .../ch.2/ch.2.xcodeproj/project.pbxproj" | 296 ++++++++++++++++++ .../contents.xcworkspacedata" | 7 + .../ch.2/ch.2/helper.swift" | 14 + .../ch.2/ch.2/main.swift" | 42 +++ ...\210\230 \353\254\270\354\240\234 1.swift" | 18 ++ ...\210\230 \353\254\270\354\240\234 2.swift" | 30 ++ ...\210\230 \353\254\270\354\240\234 3.swift" | 38 +++ ...\210\230 \353\254\270\354\240\234 4.swift" | 17 + 9 files changed, 464 insertions(+) create mode 100644 "\353\263\200\354\230\210\353\246\260/README.md" create mode 100644 "\353\263\200\354\230\210\353\246\260/ch.2/ch.2.xcodeproj/project.pbxproj" create mode 100644 "\353\263\200\354\230\210\353\246\260/ch.2/ch.2.xcodeproj/project.xcworkspace/contents.xcworkspacedata" create mode 100644 "\353\263\200\354\230\210\353\246\260/ch.2/ch.2/helper.swift" create mode 100644 "\353\263\200\354\230\210\353\246\260/ch.2/ch.2/main.swift" create mode 100644 "\353\263\200\354\230\210\353\246\260/ch.2/ch.2/\355\225\204\354\210\230 \352\265\254\355\230\204 \352\263\274\354\240\234/\355\225\204\354\210\230 \353\254\270\354\240\234 1.swift" create mode 100644 "\353\263\200\354\230\210\353\246\260/ch.2/ch.2/\355\225\204\354\210\230 \352\265\254\355\230\204 \352\263\274\354\240\234/\355\225\204\354\210\230 \353\254\270\354\240\234 2.swift" create mode 100644 "\353\263\200\354\230\210\353\246\260/ch.2/ch.2/\355\225\204\354\210\230 \352\265\254\355\230\204 \352\263\274\354\240\234/\355\225\204\354\210\230 \353\254\270\354\240\234 3.swift" create mode 100644 "\353\263\200\354\230\210\353\246\260/ch.2/ch.2/\355\225\204\354\210\230 \352\265\254\355\230\204 \352\263\274\354\240\234/\355\225\204\354\210\230 \353\254\270\354\240\234 4.swift" diff --git "a/\353\263\200\354\230\210\353\246\260/README.md" "b/\353\263\200\354\230\210\353\246\260/README.md" new file mode 100644 index 0000000..4cdac39 --- /dev/null +++ "b/\353\263\200\354\230\210\353\246\260/README.md" @@ -0,0 +1,2 @@ +# -Ch2.- +[내배캠] Ch2. 프로그래밍 기초 주차 과제 풀이 diff --git "a/\353\263\200\354\230\210\353\246\260/ch.2/ch.2.xcodeproj/project.pbxproj" "b/\353\263\200\354\230\210\353\246\260/ch.2/ch.2.xcodeproj/project.pbxproj" new file mode 100644 index 0000000..e9e257b --- /dev/null +++ "b/\353\263\200\354\230\210\353\246\260/ch.2/ch.2.xcodeproj/project.pbxproj" @@ -0,0 +1,296 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 77; + objects = { + +/* Begin PBXCopyFilesBuildPhase section */ + F90B55B82F0CB945006420D1 /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = /usr/share/man/man1/; + dstSubfolderSpec = 0; + files = ( + ); + runOnlyForDeploymentPostprocessing = 1; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + F90B55BA2F0CB945006420D1 /* ch.2 */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = ch.2; sourceTree = BUILT_PRODUCTS_DIR; }; +/* End PBXFileReference section */ + +/* Begin PBXFileSystemSynchronizedRootGroup section */ + F90B55BC2F0CB945006420D1 /* ch.2 */ = { + isa = PBXFileSystemSynchronizedRootGroup; + path = ch.2; + sourceTree = ""; + }; +/* End PBXFileSystemSynchronizedRootGroup section */ + +/* Begin PBXFrameworksBuildPhase section */ + F90B55B72F0CB945006420D1 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + F90B55B12F0CB945006420D1 = { + isa = PBXGroup; + children = ( + F90B55BC2F0CB945006420D1 /* ch.2 */, + F90B55BB2F0CB945006420D1 /* Products */, + ); + sourceTree = ""; + }; + F90B55BB2F0CB945006420D1 /* Products */ = { + isa = PBXGroup; + children = ( + F90B55BA2F0CB945006420D1 /* ch.2 */, + ); + name = Products; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + F90B55B92F0CB945006420D1 /* ch.2 */ = { + isa = PBXNativeTarget; + buildConfigurationList = F90B55C12F0CB945006420D1 /* Build configuration list for PBXNativeTarget "ch.2" */; + buildPhases = ( + F90B55B62F0CB945006420D1 /* Sources */, + F90B55B72F0CB945006420D1 /* Frameworks */, + F90B55B82F0CB945006420D1 /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + ); + fileSystemSynchronizedGroups = ( + F90B55BC2F0CB945006420D1 /* ch.2 */, + ); + name = ch.2; + packageProductDependencies = ( + ); + productName = ch.2; + productReference = F90B55BA2F0CB945006420D1 /* ch.2 */; + productType = "com.apple.product-type.tool"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + F90B55B22F0CB945006420D1 /* Project object */ = { + isa = PBXProject; + attributes = { + BuildIndependentTargetsInParallel = 1; + LastSwiftUpdateCheck = 1640; + LastUpgradeCheck = 1640; + TargetAttributes = { + F90B55B92F0CB945006420D1 = { + CreatedOnToolsVersion = 16.4; + }; + }; + }; + buildConfigurationList = F90B55B52F0CB945006420D1 /* Build configuration list for PBXProject "ch.2" */; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = F90B55B12F0CB945006420D1; + minimizedProjectReferenceProxies = 1; + preferredProjectObjectVersion = 77; + productRefGroup = F90B55BB2F0CB945006420D1 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + F90B55B92F0CB945006420D1 /* ch.2 */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXSourcesBuildPhase section */ + F90B55B62F0CB945006420D1 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + F90B55BF2F0CB945006420D1 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + DEVELOPMENT_TEAM = M6HT23N3TY; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + GCC_C_LANGUAGE_STANDARD = gnu17; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; + MACOSX_DEPLOYMENT_TARGET = 15.5; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + F90B55C02F0CB945006420D1 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + DEVELOPMENT_TEAM = M6HT23N3TY; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + GCC_C_LANGUAGE_STANDARD = gnu17; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; + MACOSX_DEPLOYMENT_TARGET = 15.5; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + SDKROOT = macosx; + SWIFT_COMPILATION_MODE = wholemodule; + }; + name = Release; + }; + F90B55C22F0CB945006420D1 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = M6HT23N3TY; + ENABLE_HARDENED_RUNTIME = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + }; + name = Debug; + }; + F90B55C32F0CB945006420D1 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = M6HT23N3TY; + ENABLE_HARDENED_RUNTIME = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + F90B55B52F0CB945006420D1 /* Build configuration list for PBXProject "ch.2" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + F90B55BF2F0CB945006420D1 /* Debug */, + F90B55C02F0CB945006420D1 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + F90B55C12F0CB945006420D1 /* Build configuration list for PBXNativeTarget "ch.2" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + F90B55C22F0CB945006420D1 /* Debug */, + F90B55C32F0CB945006420D1 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = F90B55B22F0CB945006420D1 /* Project object */; +} diff --git "a/\353\263\200\354\230\210\353\246\260/ch.2/ch.2.xcodeproj/project.xcworkspace/contents.xcworkspacedata" "b/\353\263\200\354\230\210\353\246\260/ch.2/ch.2.xcodeproj/project.xcworkspace/contents.xcworkspacedata" new file mode 100644 index 0000000..919434a --- /dev/null +++ "b/\353\263\200\354\230\210\353\246\260/ch.2/ch.2.xcodeproj/project.xcworkspace/contents.xcworkspacedata" @@ -0,0 +1,7 @@ + + + + + diff --git "a/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/helper.swift" "b/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/helper.swift" new file mode 100644 index 0000000..2cd874d --- /dev/null +++ "b/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/helper.swift" @@ -0,0 +1,14 @@ +// +// helper.swift +// ch.2 +// +// Created by 변예린 on 1/6/26. +// + +class Answer { + static let shared = Answer() + + let required1 = Required1() + let required2 = Required2() + let required3 = Required3() +} diff --git "a/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/main.swift" "b/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/main.swift" new file mode 100644 index 0000000..ea3b1fc --- /dev/null +++ "b/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/main.swift" @@ -0,0 +1,42 @@ +// +// main.swift +// ch.2 +// +// Created by 변예린 on 1/6/26. +// + +import Foundation + +let answer = Answer.shared + +//MARK: 필수 문제 + +// 1. +// - sum 호출 코드 +print(answer.required1.sum(3, 5)) + +// - calculate 호출 코드 +answer.required1.calculate(3, 5, answer.required1.sum) + + +// 2. +// - myMap 호출 코드 +print(answer.required2.myMap([1, 2, 3]) { String($0) }) + + +// 3. +// - 함수 a 호출 코드 +print(answer.required3.a([1, 2, 3, 4, 5])) + +// - 함수 b 호출 코드 +print(answer.required3.b(["가", "나", "다", "라", "마"])) + +// - 함수 c 호출 코드 +print(answer.required3.c([1, 2, 3, 4, 5])) +print(answer.required3.c(["가", "나", "다", "라", "마"])) + +// - 함수 d 호출 코드 +// print(answer.required3.d(["가"])) // 오류 +print(answer.required3.d([1, 2, 3, 4, 5])) + + diff --git "a/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/\355\225\204\354\210\230 \352\265\254\355\230\204 \352\263\274\354\240\234/\355\225\204\354\210\230 \353\254\270\354\240\234 1.swift" "b/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/\355\225\204\354\210\230 \352\265\254\355\230\204 \352\263\274\354\240\234/\355\225\204\354\210\230 \353\254\270\354\240\234 1.swift" new file mode 100644 index 0000000..4d12a72 --- /dev/null +++ "b/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/\355\225\204\354\210\230 \352\265\254\355\230\204 \352\263\274\354\240\234/\355\225\204\354\210\230 \353\254\270\354\240\234 1.swift" @@ -0,0 +1,18 @@ +// +// 필수 문제 1.swift +// ch.2 +// +// Created by 변예린 on 1/6/26. +// + +import Foundation + +struct Required1 { + let sum: (Int, Int) -> String = { + return "두 수의 합은 \($0 + $1) 입니다." + } + + func calculate (_ num1: Int, _ num2: Int, _ operation: (Int, Int) -> String) { + print(operation(num1, num2)) + } +} diff --git "a/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/\355\225\204\354\210\230 \352\265\254\355\230\204 \352\263\274\354\240\234/\355\225\204\354\210\230 \353\254\270\354\240\234 2.swift" "b/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/\355\225\204\354\210\230 \352\265\254\355\230\204 \352\263\274\354\240\234/\355\225\204\354\210\230 \353\254\270\354\240\234 2.swift" new file mode 100644 index 0000000..1ed8c44 --- /dev/null +++ "b/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/\355\225\204\354\210\230 \352\265\254\355\230\204 \352\263\274\354\240\234/\355\225\204\354\210\230 \353\254\270\354\240\234 2.swift" @@ -0,0 +1,30 @@ +// +// 필수 문제 2.swift +// ch.2 +// +// Created by 변예린 on 1/6/26. +// + +import Foundation + +struct Required2 { + // for-in 반복문 map 변환 + let numbers = [1, 2, 3, 4, 5] + lazy var result = numbers.map { String($0) } + + // 고차함수 체이닝 + func mapChain(_ arr: [Int]) -> [String] { + return arr.filter { $0 % 2 == 0 }.map { String($0) } + } + + // 고차함수 생성 + func myMap(_ arr: [Int], _ convert: (Int) -> String) -> [String] { + var result: [String] = [] + + for num in arr { + result.append(convert(num)) + } + + return result + } +} diff --git "a/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/\355\225\204\354\210\230 \352\265\254\355\230\204 \352\263\274\354\240\234/\355\225\204\354\210\230 \353\254\270\354\240\234 3.swift" "b/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/\355\225\204\354\210\230 \352\265\254\355\230\204 \352\263\274\354\240\234/\355\225\204\354\210\230 \353\254\270\354\240\234 3.swift" new file mode 100644 index 0000000..b927e92 --- /dev/null +++ "b/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/\355\225\204\354\210\230 \352\265\254\355\230\204 \352\263\274\354\240\234/\355\225\204\354\210\230 \353\254\270\354\240\234 3.swift" @@ -0,0 +1,38 @@ +// +// 필수 문제 3.swift +// ch.2 +// +// Created by 변예린 on 1/6/26. +// + +import Foundation + +struct Required3 { + // Int 배열 짝수번째 요소 제거하여 반환 + func a (_ arr: [Int]) -> [Int] { + return arr.enumerated() + .filter { $0.offset % 2 != 0 } + .map { $0.element } + } + + // String 배열 짝수번째 요소 제거하여 반환 + func b (_ arr: [String]) -> [String] { + return arr.enumerated() + .filter { $0.offset % 2 != 0 } + .map { $0.element } + } + + // 두 함수 a, b를 대체하는 함수 + func c (_ arr: [T]) -> [T] { + return arr.enumerated() + .filter { $0.offset % 2 != 0 } + .map { $0.element } + } + + // Numeric 프로토콜을 준수하는 타입을 파라미터로 받는 함수 + func d (_ arr: [D]) -> [D] { + return arr.enumerated() + .filter { $0.offset % 2 != 0 } + .map { $0.element } + } +} diff --git "a/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/\355\225\204\354\210\230 \352\265\254\355\230\204 \352\263\274\354\240\234/\355\225\204\354\210\230 \353\254\270\354\240\234 4.swift" "b/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/\355\225\204\354\210\230 \352\265\254\355\230\204 \352\263\274\354\240\234/\355\225\204\354\210\230 \353\254\270\354\240\234 4.swift" new file mode 100644 index 0000000..ff3bf8b --- /dev/null +++ "b/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/\355\225\204\354\210\230 \352\265\254\355\230\204 \352\263\274\354\240\234/\355\225\204\354\210\230 \353\254\270\354\240\234 4.swift" @@ -0,0 +1,17 @@ +// +// 필수 문제 4.swift +// ch.2 +// +// Created by 변예린 on 1/6/26. +// + +import Foundation + +struct Required4 { + +} + +protocol Introducible { + var name: String { get } + +} From 5ef443ef442913a7af57b0b0fda6dbe28cdfcdcb Mon Sep 17 00:00:00 2001 From: Bambu Date: Tue, 6 Jan 2026 18:08:32 +0900 Subject: [PATCH 03/26] =?UTF-8?q?Chore:=20=ED=95=84=EC=88=98=20=EB=AC=B8?= =?UTF-8?q?=EC=A0=9C=202=20mapChain=20=ED=98=B8=EC=B6=9C=20=EC=BD=94?= =?UTF-8?q?=EB=93=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../.gitignore" | 0 "\353\263\200\354\230\210\353\246\260/ch.2/ch.2/main.swift" | 4 ++++ 2 files changed, 4 insertions(+) rename .gitignore => "\353\263\200\354\230\210\353\246\260/.gitignore" (100%) diff --git a/.gitignore "b/\353\263\200\354\230\210\353\246\260/.gitignore" similarity index 100% rename from .gitignore rename to "\353\263\200\354\230\210\353\246\260/.gitignore" diff --git "a/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/main.swift" "b/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/main.swift" index ea3b1fc..0e45220 100644 --- "a/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/main.swift" +++ "b/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/main.swift" @@ -20,6 +20,9 @@ answer.required1.calculate(3, 5, answer.required1.sum) // 2. +// - 고차함수 체이닝 호출 코드 +print(answer.required2.mapChain([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])) + // - myMap 호출 코드 print(answer.required2.myMap([1, 2, 3]) { String($0) }) @@ -35,6 +38,7 @@ print(answer.required3.b(["가", "나", "다", "라", "마"])) print(answer.required3.c([1, 2, 3, 4, 5])) print(answer.required3.c(["가", "나", "다", "라", "마"])) + // - 함수 d 호출 코드 // print(answer.required3.d(["가"])) // 오류 print(answer.required3.d([1, 2, 3, 4, 5])) From 196d9016b1f49a08a638b29b19a4a361801e5462 Mon Sep 17 00:00:00 2001 From: Bambu Date: Wed, 7 Jan 2026 11:04:45 +0900 Subject: [PATCH 04/26] =?UTF-8?q?Feat:=20=ED=95=84=EC=88=98=20=EB=AC=B8?= =?UTF-8?q?=EC=A0=9C=204=20=EA=B5=AC=ED=98=84=20=EC=99=84=EB=A3=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 주석 및 main 호출부 수정 --- .../ch.2/ch.2/main.swift" | 52 ++++++++++++----- ...\210\230 \353\254\270\354\240\234 1.swift" | 2 + ...\210\230 \353\254\270\354\240\234 4.swift" | 58 ++++++++++++++++++- 3 files changed, 96 insertions(+), 16 deletions(-) diff --git "a/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/main.swift" "b/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/main.swift" index 0e45220..fc2ee8d 100644 --- "a/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/main.swift" +++ "b/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/main.swift" @@ -7,40 +7,66 @@ import Foundation -let answer = Answer.shared - //MARK: 필수 문제 // 1. // - sum 호출 코드 -print(answer.required1.sum(3, 5)) +print(Required1().sum(3, 5)) // - calculate 호출 코드 -answer.required1.calculate(3, 5, answer.required1.sum) +Required1().calculate(3, 5, Required1().sum) // 2. // - 고차함수 체이닝 호출 코드 -print(answer.required2.mapChain([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])) +print(Required2().mapChain([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])) // - myMap 호출 코드 -print(answer.required2.myMap([1, 2, 3]) { String($0) }) +print(Required2().myMap([1, 2, 3]) { String($0) }) // 3. // - 함수 a 호출 코드 -print(answer.required3.a([1, 2, 3, 4, 5])) +print(Required3().a([1, 2, 3, 4, 5])) // - 함수 b 호출 코드 -print(answer.required3.b(["가", "나", "다", "라", "마"])) +print(Required3().b(["가", "나", "다", "라", "마"])) // - 함수 c 호출 코드 -print(answer.required3.c([1, 2, 3, 4, 5])) -print(answer.required3.c(["가", "나", "다", "라", "마"])) +print(Required3().c([1, 2, 3, 4, 5])) +print(Required3().c(["가", "나", "다", "라", "마"])) // - 함수 d 호출 코드 // print(answer.required3.d(["가"])) // 오류 -print(answer.required3.d([1, 2, 3, 4, 5])) - - +print(Required3().d([1, 2, 3, 4, 5])) + + +// 4. +// - Robot.name 프로퍼티 옵저버 확인 +var robot = Robot(name: "로봇") +robot.name = "로보트" +robot.name = "로보트" // 문자열 출력 X + +// - [Introducible] 타입 배열 정의, 배열을 순회하며 고유 메서드 호출 +var introducibleArr: [Introducible] = [] + +introducibleArr.append(Robot(name: "로봇")) +introducibleArr.append(Cat(name: "고양이")) +introducibleArr.append(Dog(name: "강아지")) + +introducibleArr.enumerated().forEach { index, element in + switch index { + case 0: + let instance = element as? Robot + instance?.batterCharge() + case 1: + let instance = element as? Cat + instance?.meow() + case 2: + let instance = element as? Dog + instance?.bark() + default: + break + } +} diff --git "a/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/\355\225\204\354\210\230 \352\265\254\355\230\204 \352\263\274\354\240\234/\355\225\204\354\210\230 \353\254\270\354\240\234 1.swift" "b/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/\355\225\204\354\210\230 \352\265\254\355\230\204 \352\263\274\354\240\234/\355\225\204\354\210\230 \353\254\270\354\240\234 1.swift" index 4d12a72..c7a8f38 100644 --- "a/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/\355\225\204\354\210\230 \352\265\254\355\230\204 \352\263\274\354\240\234/\355\225\204\354\210\230 \353\254\270\354\240\234 1.swift" +++ "b/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/\355\225\204\354\210\230 \352\265\254\355\230\204 \352\263\274\354\240\234/\355\225\204\354\210\230 \353\254\270\354\240\234 1.swift" @@ -8,10 +8,12 @@ import Foundation struct Required1 { + // 두 개의 Int값을 파라미터로 받고, 하나의 String 값을 반환하는 클로저 설계 let sum: (Int, Int) -> String = { return "두 수의 합은 \($0 + $1) 입니다." } + // sum과 동일한 타입의 클로저를 파라미터로 받고, 반환 값이 없는 함수 func calculate (_ num1: Int, _ num2: Int, _ operation: (Int, Int) -> String) { print(operation(num1, num2)) } diff --git "a/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/\355\225\204\354\210\230 \352\265\254\355\230\204 \352\263\274\354\240\234/\355\225\204\354\210\230 \353\254\270\354\240\234 4.swift" "b/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/\355\225\204\354\210\230 \352\265\254\355\230\204 \352\263\274\354\240\234/\355\225\204\354\210\230 \353\254\270\354\240\234 4.swift" index ff3bf8b..c4b7821 100644 --- "a/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/\355\225\204\354\210\230 \352\265\254\355\230\204 \352\263\274\354\240\234/\355\225\204\354\210\230 \353\254\270\354\240\234 4.swift" +++ "b/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/\355\225\204\354\210\230 \352\265\254\355\230\204 \352\263\274\354\240\234/\355\225\204\354\210\230 \353\254\270\354\240\234 4.swift" @@ -7,11 +7,63 @@ import Foundation -struct Required4 { +// 프로토콜 정의 +protocol Introducible { + var name: String { get } + func introduce() -> String } -protocol Introducible { - var name: String { get } +// Robot 타입 정의 +struct Robot: Introducible { + var name: String { + didSet { // 변경될 때마다 변경 이전값, 이후값 출력 + if oldValue != name { + print(""" + name 변경 알림 + 변경 이전 값: \(oldValue) + 변경 이후 값: \(name) + """) + } + } + } + func introduce() -> String { + return "안녕하세요, 저는 \(name)입니다." + } + + // 고유 메서드 + func batterCharge() { + print("배터리 충전중...") + } } + +// Cat 타입 정의 +struct Cat: Introducible { + var name: String + + func introduce() -> String { + return "야옹, 저는 \(name)입니다." + } + + // 고유 메서드 + func meow() { + print("야옹") + } +} + +// Dog 타입 정의 +struct Dog: Introducible { + var name: String + + func introduce() -> String { + return "멍멍! 저는 \(name)입니다." + } + + // 고유 메서드 + func bark() { + print("멍멍!") + } +} + + From ba39efdb40a571126818a6301d94a83af124fea3 Mon Sep 17 00:00:00 2001 From: Bambu Date: Wed, 7 Jan 2026 11:15:55 +0900 Subject: [PATCH 05/26] =?UTF-8?q?Chore:=20=EA=B3=A0=EC=9C=A0=EB=A9=94?= =?UTF-8?q?=EC=84=9C=EB=93=9C=20=ED=98=B8=EC=B6=9C=20=EC=BD=94=EB=93=9C=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit introducibleArr.enumerated().forEach 문 (인덱스로 매칭) -> for-in 반복문 (타입 매칭) --- .../ch.2/ch.2/main.swift" | 15 +++++++-------- ...\354\210\230 \353\254\270\354\240\234 4.swift" | 2 +- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git "a/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/main.swift" "b/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/main.swift" index fc2ee8d..0b763a3 100644 --- "a/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/main.swift" +++ "b/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/main.swift" @@ -51,22 +51,21 @@ robot.name = "로보트" // 문자열 출력 X // - [Introducible] 타입 배열 정의, 배열을 순회하며 고유 메서드 호출 var introducibleArr: [Introducible] = [] -introducibleArr.append(Robot(name: "로봇")) +introducibleArr.append(robot) introducibleArr.append(Cat(name: "고양이")) introducibleArr.append(Dog(name: "강아지")) -introducibleArr.enumerated().forEach { index, element in - switch index { - case 0: +for element in introducibleArr { + if element is Robot { let instance = element as? Robot - instance?.batterCharge() - case 1: + instance?.batteryCharge() + } else if element is Cat { let instance = element as? Cat instance?.meow() - case 2: + } else if element is Dog { let instance = element as? Dog instance?.bark() - default: + } else { break } } diff --git "a/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/\355\225\204\354\210\230 \352\265\254\355\230\204 \352\263\274\354\240\234/\355\225\204\354\210\230 \353\254\270\354\240\234 4.swift" "b/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/\355\225\204\354\210\230 \352\265\254\355\230\204 \352\263\274\354\240\234/\355\225\204\354\210\230 \353\254\270\354\240\234 4.swift" index c4b7821..72a03e8 100644 --- "a/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/\355\225\204\354\210\230 \352\265\254\355\230\204 \352\263\274\354\240\234/\355\225\204\354\210\230 \353\254\270\354\240\234 4.swift" +++ "b/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/\355\225\204\354\210\230 \352\265\254\355\230\204 \352\263\274\354\240\234/\355\225\204\354\210\230 \353\254\270\354\240\234 4.swift" @@ -33,7 +33,7 @@ struct Robot: Introducible { } // 고유 메서드 - func batterCharge() { + func batteryCharge() { print("배터리 충전중...") } } From 57c2291f05136a81e614d2a13e22e6be0b366695 Mon Sep 17 00:00:00 2001 From: Bambu Date: Wed, 7 Jan 2026 12:09:18 +0900 Subject: [PATCH 06/26] =?UTF-8?q?Feat:=20=ED=95=84=EC=88=98=20=EB=AC=B8?= =?UTF-8?q?=EC=A0=9C=205=20=EA=B5=AC=ED=98=84=20=EC=99=84=EB=A3=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ch.2/ch.2/main.swift" | 13 +++++ ...\210\230 \353\254\270\354\240\234 5.swift" | 48 +++++++++++++++++++ 2 files changed, 61 insertions(+) create mode 100644 "\353\263\200\354\230\210\353\246\260/ch.2/ch.2/\355\225\204\354\210\230 \352\265\254\355\230\204 \352\263\274\354\240\234/\355\225\204\354\210\230 \353\254\270\354\240\234 5.swift" diff --git "a/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/main.swift" "b/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/main.swift" index 0b763a3..9ba976a 100644 --- "a/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/main.swift" +++ "b/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/main.swift" @@ -69,3 +69,16 @@ for element in introducibleArr { break } } + +// 5. +// - throwing function 호출 +do { + try print(Required5() + .predictDeliveryDay(for: "우리집", status: .notStarted)) +} catch DeliveryError.notstarted { + print("아직 배송이 시작되지 않았습니다.") +} catch DeliveryError.invalidAddress { + print("유효하지 않은 주소입니다. 주소를 다시 입력해주세요.") +} catch DeliveryError.systemError(reason: let reason) { + print("시스템 에러입니다. 사유: \(reason)") +} diff --git "a/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/\355\225\204\354\210\230 \352\265\254\355\230\204 \352\263\274\354\240\234/\355\225\204\354\210\230 \353\254\270\354\240\234 5.swift" "b/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/\355\225\204\354\210\230 \352\265\254\355\230\204 \352\263\274\354\240\234/\355\225\204\354\210\230 \353\254\270\354\240\234 5.swift" new file mode 100644 index 0000000..68cdf5a --- /dev/null +++ "b/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/\355\225\204\354\210\230 \352\265\254\355\230\204 \352\263\274\354\240\234/\355\225\204\354\210\230 \353\254\270\354\240\234 5.swift" @@ -0,0 +1,48 @@ +// +// 필수 문제 5.swift +// ch.2 +// +// Created by 변예린 on 1/7/26. +// + +import Foundation + +struct Required5 { + + var remainingDay: Int = 3 // 함수를 위한 임의 변수 정의 + + // 요구 throwing function + func predictDeliveryDay(for address: String, status: DeliveryStatus) throws -> String { + + // 주소가 잘못된 경우 + if address.isEmpty { + throw DeliveryError.invalidAddress + } + + // DeliveryStatus에 따른 분기 처리 + switch status { + case .notStarted: // 배송이 아직 시작되지 않은 경우 + throw DeliveryError.notstarted + + case .error: // 시스템 서버 에러로 예측이 불가능한 경우 + throw DeliveryError.systemError(reason: "서버 에러") + + case .inTransit(dayRemaining: let day): // 정상 배송 상태 + return "배송까지 \(day)일 남았습니다." + } + } +} + +// 배송 상태 열거형 +enum DeliveryStatus { + case notStarted + case inTransit(dayRemaining: Int) + case error +} + +// 에러 타입 열거형 +enum DeliveryError: Error { + case invalidAddress + case notstarted + case systemError(reason: String) +} From 989ca780cdc9aaa3e8cc840448a79ebc68255b26 Mon Sep 17 00:00:00 2001 From: Bambu Date: Wed, 7 Jan 2026 12:12:40 +0900 Subject: [PATCH 07/26] =?UTF-8?q?Chore:=20=ED=95=84=EC=88=98=20=EB=AC=B8?= =?UTF-8?q?=EC=A0=9C=205=20=EC=9E=84=EC=9D=98=20=EB=B3=80=EC=88=98=20?= =?UTF-8?q?=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../\355\225\204\354\210\230 \353\254\270\354\240\234 5.swift" | 3 --- 1 file changed, 3 deletions(-) diff --git "a/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/\355\225\204\354\210\230 \352\265\254\355\230\204 \352\263\274\354\240\234/\355\225\204\354\210\230 \353\254\270\354\240\234 5.swift" "b/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/\355\225\204\354\210\230 \352\265\254\355\230\204 \352\263\274\354\240\234/\355\225\204\354\210\230 \353\254\270\354\240\234 5.swift" index 68cdf5a..7838447 100644 --- "a/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/\355\225\204\354\210\230 \352\265\254\355\230\204 \352\263\274\354\240\234/\355\225\204\354\210\230 \353\254\270\354\240\234 5.swift" +++ "b/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/\355\225\204\354\210\230 \352\265\254\355\230\204 \352\263\274\354\240\234/\355\225\204\354\210\230 \353\254\270\354\240\234 5.swift" @@ -8,9 +8,6 @@ import Foundation struct Required5 { - - var remainingDay: Int = 3 // 함수를 위한 임의 변수 정의 - // 요구 throwing function func predictDeliveryDay(for address: String, status: DeliveryStatus) throws -> String { From 4895e995f69eb03022d168019b0e1140ae6a8dfc Mon Sep 17 00:00:00 2001 From: Bambu Date: Wed, 7 Jan 2026 12:13:25 +0900 Subject: [PATCH 08/26] =?UTF-8?q?Chore:=20=EA=B3=A7=EB=B0=B1=20=EC=A0=9C?= =?UTF-8?q?=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../\355\225\204\354\210\230 \353\254\270\354\240\234 5.swift" | 1 - 1 file changed, 1 deletion(-) diff --git "a/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/\355\225\204\354\210\230 \352\265\254\355\230\204 \352\263\274\354\240\234/\355\225\204\354\210\230 \353\254\270\354\240\234 5.swift" "b/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/\355\225\204\354\210\230 \352\265\254\355\230\204 \352\263\274\354\240\234/\355\225\204\354\210\230 \353\254\270\354\240\234 5.swift" index 7838447..95254fe 100644 --- "a/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/\355\225\204\354\210\230 \352\265\254\355\230\204 \352\263\274\354\240\234/\355\225\204\354\210\230 \353\254\270\354\240\234 5.swift" +++ "b/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/\355\225\204\354\210\230 \352\265\254\355\230\204 \352\263\274\354\240\234/\355\225\204\354\210\230 \353\254\270\354\240\234 5.swift" @@ -10,7 +10,6 @@ import Foundation struct Required5 { // 요구 throwing function func predictDeliveryDay(for address: String, status: DeliveryStatus) throws -> String { - // 주소가 잘못된 경우 if address.isEmpty { throw DeliveryError.invalidAddress From c0b5d1554642a19f03e63b009d0702ff8fee1f0e Mon Sep 17 00:00:00 2001 From: Bambu Date: Wed, 7 Jan 2026 12:16:02 +0900 Subject: [PATCH 09/26] =?UTF-8?q?Docs:=20helper=20=ED=8C=8C=EC=9D=BC=20?= =?UTF-8?q?=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ch.2/ch.2/helper.swift" | 14 -------------- 1 file changed, 14 deletions(-) delete mode 100644 "\353\263\200\354\230\210\353\246\260/ch.2/ch.2/helper.swift" diff --git "a/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/helper.swift" "b/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/helper.swift" deleted file mode 100644 index 2cd874d..0000000 --- "a/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/helper.swift" +++ /dev/null @@ -1,14 +0,0 @@ -// -// helper.swift -// ch.2 -// -// Created by 변예린 on 1/6/26. -// - -class Answer { - static let shared = Answer() - - let required1 = Required1() - let required2 = Required2() - let required3 = Required3() -} From 39cc43a507ade7e00705ba5a0f4e5032a5bc0fd0 Mon Sep 17 00:00:00 2001 From: Bambu Date: Wed, 7 Jan 2026 12:25:35 +0900 Subject: [PATCH 10/26] =?UTF-8?q?Chore:=20=ED=95=84=EC=88=98=20=EB=AC=B8?= =?UTF-8?q?=EC=A0=9C=204=20=EC=98=88=EC=99=B8=20=EC=B2=98=EB=A6=AC?= =?UTF-8?q?=EB=AC=B8=20=EC=88=98=EC=A0=95=20-=20break=20->=20continue?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- "\353\263\200\354\230\210\353\246\260/ch.2/ch.2/main.swift" | 3 ++- .../\355\225\204\354\210\230 \353\254\270\354\240\234 4.swift" | 1 - 2 files changed, 2 insertions(+), 2 deletions(-) diff --git "a/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/main.swift" "b/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/main.swift" index 9ba976a..d2b340a 100644 --- "a/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/main.swift" +++ "b/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/main.swift" @@ -66,10 +66,11 @@ for element in introducibleArr { let instance = element as? Dog instance?.bark() } else { - break + continue } } + // 5. // - throwing function 호출 do { diff --git "a/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/\355\225\204\354\210\230 \352\265\254\355\230\204 \352\263\274\354\240\234/\355\225\204\354\210\230 \353\254\270\354\240\234 4.swift" "b/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/\355\225\204\354\210\230 \352\265\254\355\230\204 \352\263\274\354\240\234/\355\225\204\354\210\230 \353\254\270\354\240\234 4.swift" index 72a03e8..c9ba10b 100644 --- "a/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/\355\225\204\354\210\230 \352\265\254\355\230\204 \352\263\274\354\240\234/\355\225\204\354\210\230 \353\254\270\354\240\234 4.swift" +++ "b/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/\355\225\204\354\210\230 \352\265\254\355\230\204 \352\263\274\354\240\234/\355\225\204\354\210\230 \353\254\270\354\240\234 4.swift" @@ -66,4 +66,3 @@ struct Dog: Introducible { } } - From 7fcad459fec742d343492eeffba4fb5482bfd0cc Mon Sep 17 00:00:00 2001 From: Bambu Date: Thu, 8 Jan 2026 10:43:08 +0900 Subject: [PATCH 11/26] =?UTF-8?q?Feat:=20=EB=8F=84=EC=A0=84=20=EB=AC=B8?= =?UTF-8?q?=EC=A0=9C=201=20=EA=B5=AC=ED=98=84=20=EC=99=84=EB=A3=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ch.2/ch.2/main.swift" | 29 +++++ ...\240\204 \353\254\270\354\240\234 1.swift" | 119 ++++++++++++++++++ 2 files changed, 148 insertions(+) create mode 100644 "\353\263\200\354\230\210\353\246\260/ch.2/ch.2/\353\217\204\354\240\204 \352\263\274\354\240\234/\353\217\204\354\240\204 \353\254\270\354\240\234 1.swift" diff --git "a/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/main.swift" "b/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/main.swift" index d2b340a..002c894 100644 --- "a/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/main.swift" +++ "b/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/main.swift" @@ -83,3 +83,32 @@ do { } catch DeliveryError.systemError(reason: let reason) { print("시스템 에러입니다. 사유: \(reason)") } + + + +//MARK: 도전 문제 + +// 1. +// - ElectricCar +let electric = ElectricCar(brand: "테슬라", model: "Y", modelYear: "2026") + +electric.drive() +electric.stop() +electric.park() +print(electric.engine.type) + +// - HybridCar +let hybrid = HybridCar(brand: "기아", model: "셀토스", modelYear: "2026") + +hybrid.drive() +hybrid.switchEngine(to: .electric) +hybrid.switchEngine(to: .electric) +hybrid.switchEngine(to: .hydrogen) + +/* + Q. 상속을 사용하여 기능을 추가하는 것과, 프로토콜 채택을 통해서 기능을 추가하는 것의 장단점, 차이를 고민하고 주석으로 서술해주세요. + A. 상속의 경우, 부모 클래스에 정의된 기능을 모두 사용할 수 있으며 재정의를 통해 커스텀할 수 있다는 장점이 있다. 그러나 상속 받은 클래스에는 필요 없는 부분까지 강제적으로 가져야한다는 단점이 있다. + 반면, 프로토콜은 프로토콜에 정의된 기능만 구현하면 된다는 장점이 있다. 클래스처럼 필요없는 기능까지 가지지 않으므로 공통된 몇 가지 기능(혹은 프로퍼티)만 가지길 원한다면 프로토콜이 유리하다. + 즉, 대부분 비슷하면서도 조금씩 차이를 갖는 경우라면 상속이, 공통적인 몇 가지만 여러 객체에서 가지길 원하는 경우라면 프로토콜을 사용하는 것이 좋다. + */ + diff --git "a/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/\353\217\204\354\240\204 \352\263\274\354\240\234/\353\217\204\354\240\204 \353\254\270\354\240\234 1.swift" "b/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/\353\217\204\354\240\204 \352\263\274\354\240\234/\353\217\204\354\240\204 \353\254\270\354\240\234 1.swift" new file mode 100644 index 0000000..ad6c552 --- /dev/null +++ "b/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/\353\217\204\354\240\204 \352\263\274\354\240\234/\353\217\204\354\240\204 \353\254\270\354\240\234 1.swift" @@ -0,0 +1,119 @@ +// +// 도전 문제 1.swift +// ch.2 +// +// Created by 변예린 on 1/8/26. +// + +import Foundation + +//MARK: 자동차 정의 +// Car 클래스 설계 +class Car { + var brand: String + var model: String + var modelYear: String + let engine: Engine + + init(brand: String, model: String, modelYear: String, engine: Engine) { + self.brand = brand + self.model = model + self.modelYear = modelYear + self.engine = engine + } + + // 접근 제어자와 함께 동작 정의 + public func drive() { + print("[\(brand) \(model)] 주행 중...") + } + + public func stop() { + print("[\(brand) \(model)] 정지") + } + + public func park() { + print("[\(brand) \(model)] 주차") + } +} + +// Car를 상속한 ElectricCar 설계 +class ElectricCar: Car { + // ElectricEngine 타입의 Engine 사용 + init(brand: String, model: String, modelYear: String) { + super.init(brand: brand, model: model, modelYear: modelYear, engine: ElectricEngine()) + } +} + +// Car를 상속한 HybridCar 설계 +class HybridCar: Car { + // HydrogenEngine 타입의 Engine 사용 + init(brand: String, model: String, modelYear: String) { + super.init(brand: brand, model: model, modelYear: modelYear, engine: HydrogenEngine()) + } + + func switchEngine(to type: EngineType) { + let hybridEngine = engine as! HydrogenEngine + hybridEngine.switchRunningEngine(to: type) + } +} + +//MARK: 엔진 정의 +// 엔진 열거형 타입 정의 - switch 기능의 편리성을 위해 +enum EngineType { + case electric, gasoline, hydrogen +} + +// Engine 커스텀 타입 정의 +class Engine { + var type: EngineType + + init(_ type: EngineType) { + self.type = type + } +} + +// Electric Engine 타입 정의 +class ElectricEngine: Engine { + init() { + super.init(.electric) + } +} + +// Gasolin Engine 타입 정의 +class GasolineEngine: Engine { + init() { + super.init(.gasoline) + } +} + +// HydrogenEngine 정의 +class HydrogenEngine: Engine { + // 현재 작동중인 엔진 + private var running: Engine = GasolineEngine() { + didSet { + print("현재 가동중인 엔진이 \(oldValue.type)에서 \(running.type)으로 변경되었습니다.") + } + } + + init() { + super.init(.hydrogen) + } + + // 엔진 전환 + func switchRunningEngine(to type: EngineType) { + if running.type == type { + print("이미 \(type) 엔진으로 작동 중입니다.") + return + } + + switch type { + case .electric: + running = ElectricEngine() + case .gasoline: + running = GasolineEngine() + case .hydrogen: + print("가솔린 / 전기 엔진 중 하나로만 전환 가능합니다.") + } + } +} + From 8297158f8671344b1db1266a51ea7cba0d92242d Mon Sep 17 00:00:00 2001 From: Bambu Date: Thu, 8 Jan 2026 11:12:15 +0900 Subject: [PATCH 12/26] =?UTF-8?q?Chore:=20READ=20ME=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../README.md" | 100 +++++++++++++++++- ...\240\204 \353\254\270\354\240\234 1.swift" | 10 +- 2 files changed, 103 insertions(+), 7 deletions(-) diff --git "a/\353\263\200\354\230\210\353\246\260/README.md" "b/\353\263\200\354\230\210\353\246\260/README.md" index 4cdac39..983c8df 100644 --- "a/\353\263\200\354\230\210\353\246\260/README.md" +++ "b/\353\263\200\354\230\210\353\246\260/README.md" @@ -1,2 +1,98 @@ -# -Ch2.- -[내배캠] Ch2. 프로그래밍 기초 주차 과제 풀이 +# [내배캠] Ch2. 프로그래밍 기초 주차 과제 풀이 + +## main.swift +문제에서 구현한 함수를 호출하는 파일입니다. + +각 과제는 대부분 클래스로 구현된 경우를 제외하고 구조체로 작성되었습니다. 해당하는 구조체를 생성하여 함수를 호출합니다. + +## 필수 문제 +### 4) +각 객체의 고유 메서드를 호출하는 함수의 경우, 처음에는 `introducibleArr.enumerated().forEach`를 활용하였습니다. + +```swift +introducibleArr.enumerated().forEach { index, element in + switch index { + case 0: + let instance = element as? Robot + instance?.batteryCharge() + case 1: + let instance = element as? Cat + instance?.meow() + case 2: + let instance = element as? Dog + instance?.bark() + default: + break + } +} +``` + +그러나 위 방법은 인스턴스 자체의 타입보다 배열의 인덱스에 의존한다고 판단했습니다. +따라서 for-in 반복문과 `is` 연산자를 활용하여 인스턴스의 타입을 매칭하는 방법으로 수정하였습니다. + +## 도전 문제 +### 1) +**커스텀 Engine 타입** +처음에는 열거형 타입으로 정의했으나 제시문에서 'ElectricEngine 타입의 Engine 을 사용해야합니다.' 라는 언급이 있어 클래스로 바꾸었습니다. + +각 자식 클래스(`ElectricEngine` 등)는 엔진 타입을 내부에서 주어진 기본값으로 초기화합니다. + +열거형 `EngineType`은 `switchEngine(to:)` 함수에서 인자를 안전하게 입력받기 위해 남겨두었습니다. + +**HydrogenEngine** +```swift +class HydrogenEngine: Engine { + // 현재 작동 중인 엔진 + private var running: Engine = GasolineEngine() { + didSet { + print("현재 작동 중인 엔진이 \(oldValue.type)에서 \(running.type)으로 변경되었습니다.") + } + } +``` + +다른 엔진 자식 클래스와 달리 현재 작동중인 엔진을 의미하는 `running` 변수를 가집니다. + +`HybridCar`는 `HydrogenEngine`을 가지는데, `switchEngine(to:)`를 한다고 해서 `HybridCar.engine`이 `HydrogenEngine`이 아닌 완전히 다른 엔진으로 바뀌어서는 안된다고 생각했기 때문입니다. (그러면 더이상 하이브리드 차가 아니지 않을까라고 생각했습니다.) + +따라서 작동 중임을 나타내는 변수를 따로 정의하였습니다. + +`running` 변수는 엔진의 동작으로만 변경될 수 있도록 `private` 접근자를 사용하였습니다. +프로퍼티 옵저버를 통해 어떻게 변경되었는지도 알 수 있도록 하였습니다. + +```swift + // 엔진 전환 + func switchRunningEngine(to type: EngineType) { + if running.type == type { + print("이미 \(type) 엔진으로 작동 중입니다.") + return + } + + switch type { + case .electric: + running = ElectricEngine() + case .gasoline: + running = GasolineEngine() + case .hydrogen: + print("가솔린 / 전기 엔진 중 하나로만 전환 가능합니다.") + } + } +} +``` + +(자동차의 실제 작동 원리는 모르지만) +작동 중인 엔진을 실질적으로 변경시키는 것은 `HybridCar`가 아닌 `HybridEngine`이라고 생각했기 때문에 본 클래스 내에서 `running`을 변경시키는 `func switchRunningEngine(to type:)`을 구현하였습니다. + +**HybridCar** + +```swift +class HybridCar: Car { + func switchEngine(to type: EngineType) { + let hybridEngine = engine as! HydrogenEngine + hybridEngine.switchRunningEngine(to: type) + } +} +``` + +문제에서 요구한 `func switchEngine(to:)`는 위에서 언급했듯이 실질적인 동작은 엔진이 해야한다고 생각했으므로 `HybridEngine.switchRunningEngine(to:)`를 동작시키도록 구현하였습니다. + +`Car` 클래스의 `engine` 변수는 `Engine`타입이므로 메소드를 사용하기 위해 `HydrogenEngine`으로 다운캐스팅 해주었습니다. diff --git "a/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/\353\217\204\354\240\204 \352\263\274\354\240\234/\353\217\204\354\240\204 \353\254\270\354\240\234 1.swift" "b/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/\353\217\204\354\240\204 \352\263\274\354\240\234/\353\217\204\354\240\204 \353\254\270\354\240\234 1.swift" index ad6c552..6bd9fe4 100644 --- "a/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/\353\217\204\354\240\204 \352\263\274\354\240\234/\353\217\204\354\240\204 \353\254\270\354\240\234 1.swift" +++ "b/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/\353\217\204\354\240\204 \352\263\274\354\240\234/\353\217\204\354\240\204 \353\254\270\354\240\234 1.swift" @@ -10,9 +10,9 @@ import Foundation //MARK: 자동차 정의 // Car 클래스 설계 class Car { - var brand: String - var model: String - var modelYear: String + let brand: String + let model: String + let modelYear: String let engine: Engine init(brand: String, model: String, modelYear: String, engine: Engine) { @@ -88,10 +88,10 @@ class GasolineEngine: Engine { // HydrogenEngine 정의 class HydrogenEngine: Engine { - // 현재 작동중인 엔진 + // 현재 작동 중인 엔진 private var running: Engine = GasolineEngine() { didSet { - print("현재 가동중인 엔진이 \(oldValue.type)에서 \(running.type)으로 변경되었습니다.") + print("현재 작동 중인 엔진이 \(oldValue.type)에서 \(running.type)으로 변경되었습니다.") } } From 6198aea2f88f49c5a67079a6e731ee041f4f2a4f Mon Sep 17 00:00:00 2001 From: Bambu Date: Thu, 8 Jan 2026 11:15:10 +0900 Subject: [PATCH 13/26] =?UTF-8?q?Docs:=20READ=20ME=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../README.md" => README.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) rename "\353\263\200\354\230\210\353\246\260/README.md" => README.md (97%) diff --git "a/\353\263\200\354\230\210\353\246\260/README.md" b/README.md similarity index 97% rename from "\353\263\200\354\230\210\353\246\260/README.md" rename to README.md index 983c8df..f853dfb 100644 --- "a/\353\263\200\354\230\210\353\246\260/README.md" +++ b/README.md @@ -32,14 +32,15 @@ introducibleArr.enumerated().forEach { index, element in ## 도전 문제 ### 1) -**커스텀 Engine 타입** +**1️⃣ 커스텀 Engine 타입** + 처음에는 열거형 타입으로 정의했으나 제시문에서 'ElectricEngine 타입의 Engine 을 사용해야합니다.' 라는 언급이 있어 클래스로 바꾸었습니다. 각 자식 클래스(`ElectricEngine` 등)는 엔진 타입을 내부에서 주어진 기본값으로 초기화합니다. 열거형 `EngineType`은 `switchEngine(to:)` 함수에서 인자를 안전하게 입력받기 위해 남겨두었습니다. -**HydrogenEngine** +**2️⃣ HydrogenEngine** ```swift class HydrogenEngine: Engine { // 현재 작동 중인 엔진 @@ -82,7 +83,7 @@ class HydrogenEngine: Engine { (자동차의 실제 작동 원리는 모르지만) 작동 중인 엔진을 실질적으로 변경시키는 것은 `HybridCar`가 아닌 `HybridEngine`이라고 생각했기 때문에 본 클래스 내에서 `running`을 변경시키는 `func switchRunningEngine(to type:)`을 구현하였습니다. -**HybridCar** +**3️⃣HybridCar** ```swift class HybridCar: Car { From 3a26a1ae32949c14490cbec1ecf926d1b01e8eb8 Mon Sep 17 00:00:00 2001 From: Bambu Date: Thu, 8 Jan 2026 11:52:18 +0900 Subject: [PATCH 14/26] =?UTF-8?q?Feat:=20=EB=8F=84=EC=A0=84=20=EB=AC=B8?= =?UTF-8?q?=EC=A0=9C=202=20=EA=B5=AC=ED=98=84=20=EC=99=84=EB=A3=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 37 +++++++++++++++++++ .../ch.2/ch.2/main.swift" | 11 +++++- ...\240\204 \353\254\270\354\240\234 2.swift" | 18 +++++++++ 3 files changed, 65 insertions(+), 1 deletion(-) create mode 100644 "\353\263\200\354\230\210\353\246\260/ch.2/ch.2/\353\217\204\354\240\204 \352\263\274\354\240\234/\353\217\204\354\240\204 \353\254\270\354\240\234 2.swift" diff --git a/README.md b/README.md index f853dfb..7c5fea3 100644 --- a/README.md +++ b/README.md @@ -97,3 +97,40 @@ class HybridCar: Car { 문제에서 요구한 `func switchEngine(to:)`는 위에서 언급했듯이 실질적인 동작은 엔진이 해야한다고 생각했으므로 `HybridEngine.switchRunningEngine(to:)`를 동작시키도록 구현하였습니다. `Car` 클래스의 `engine` 변수는 `Engine`타입이므로 메소드를 사용하기 위해 `HydrogenEngine`으로 다운캐스팅 해주었습니다. + +### 2) +기존에는 구조체 자체에서 제네릭 타입에 프로토콜을 제한했습니다. + +```swift +struct SortableBox { + var items: [T] + + mutating func sortItems() { + items.sort(by: <) + } +} +``` + +그러나 위 방법은 `SortableBox` 인스턴스 생성 당시 제네릭 타입이 `Comparable` 프로토콜을 준수하고 있지 않으면 바로 오류가 발생하게 됩니다. + +문제에서는 '타입 T가 `Comparable`을 준수할 때만 메서드 사용 가능', '`Comparable`을 따르지 않을 경우 `sortItems()` 호출 시 컴파일 오류 발생'이라는 조건을 제시합니다. + +즉, 위 코드는 컴파일 오류 시점이 '생성 당시'이므로 문제의 '호출 시'와는 상이합니다. + +튜터님의 조언으로 where 조건을 사용하여 해결되었습니다. + +```swift +struct SortableBox { + var items: [T] +} + +extension SortableBox where T: Comparable { + mutating func sortItems() { + items.sort(by: <) + } +} +``` + +→ 타입 T가 `Comparable`을 준수하지 않으면 `sortItems()` 메소드는 보이지 않습니다. + +위 패턴은 매우 다양하게 사용될 수 있으므로 꼭 기억해두겠습니다! diff --git "a/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/main.swift" "b/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/main.swift" index 002c894..bfd803c 100644 --- "a/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/main.swift" +++ "b/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/main.swift" @@ -105,10 +105,19 @@ hybrid.switchEngine(to: .electric) hybrid.switchEngine(to: .electric) hybrid.switchEngine(to: .hydrogen) +// - 상속을 사용하여 기능을 추가하는 것과, 프로토콜 채택을 통해서 기능을 추가하는 것의 장단점, 차이를 고민하고 주석으로 서술해주세요. /* - Q. 상속을 사용하여 기능을 추가하는 것과, 프로토콜 채택을 통해서 기능을 추가하는 것의 장단점, 차이를 고민하고 주석으로 서술해주세요. A. 상속의 경우, 부모 클래스에 정의된 기능을 모두 사용할 수 있으며 재정의를 통해 커스텀할 수 있다는 장점이 있다. 그러나 상속 받은 클래스에는 필요 없는 부분까지 강제적으로 가져야한다는 단점이 있다. 반면, 프로토콜은 프로토콜에 정의된 기능만 구현하면 된다는 장점이 있다. 클래스처럼 필요없는 기능까지 가지지 않으므로 공통된 몇 가지 기능(혹은 프로퍼티)만 가지길 원한다면 프로토콜이 유리하다. 즉, 대부분 비슷하면서도 조금씩 차이를 갖는 경우라면 상속이, 공통적인 몇 가지만 여러 객체에서 가지길 원하는 경우라면 프로토콜을 사용하는 것이 좋다. */ + +// 2. +// - sortItems() +var comparableBox = SortableBox(items: [1, 60, 3, 8, 24]) +comparableBox.sortItems() +print(comparableBox.items) + +var incomparableBox = SortableBox(items: [electric, hybrid]) // T: Car +// incomparableBox.sortItems() // 컴파일 에러 발생 diff --git "a/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/\353\217\204\354\240\204 \352\263\274\354\240\234/\353\217\204\354\240\204 \353\254\270\354\240\234 2.swift" "b/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/\353\217\204\354\240\204 \352\263\274\354\240\234/\353\217\204\354\240\204 \353\254\270\354\240\234 2.swift" new file mode 100644 index 0000000..508875e --- /dev/null +++ "b/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/\353\217\204\354\240\204 \352\263\274\354\240\234/\353\217\204\354\240\204 \353\254\270\354\240\234 2.swift" @@ -0,0 +1,18 @@ +// +// 도전 문제 2.swift +// ch.2 +// +// Created by 변예린 on 1/8/26. +// + +import Foundation + +struct SortableBox { + var items: [T] +} + +extension SortableBox where T: Comparable { + mutating func sortItems() { + items.sort(by: <) + } +} From e618890560d34fe44677ad0bd0e62dc4cc991a97 Mon Sep 17 00:00:00 2001 From: Bambu Date: Thu, 8 Jan 2026 11:54:24 +0900 Subject: [PATCH 15/26] =?UTF-8?q?Chore:=20Read=20ME=20=EC=86=8C=EC=A0=9C?= =?UTF-8?q?=EB=AA=A9=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 7c5fea3..0fe4b79 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ 각 과제는 대부분 클래스로 구현된 경우를 제외하고 구조체로 작성되었습니다. 해당하는 구조체를 생성하여 함수를 호출합니다. ## 필수 문제 -### 4) +### 4) 여러 타입에 "자기소개" 기능 부여하기 각 객체의 고유 메서드를 호출하는 함수의 경우, 처음에는 `introducibleArr.enumerated().forEach`를 활용하였습니다. ```swift @@ -31,7 +31,7 @@ introducibleArr.enumerated().forEach { index, element in 따라서 for-in 반복문과 `is` 연산자를 활용하여 인스턴스의 타입을 매칭하는 방법으로 수정하였습니다. ## 도전 문제 -### 1) +### 1) '자동차' 개념으로 객체 지향 설계하기 **1️⃣ 커스텀 Engine 타입** 처음에는 열거형 타입으로 정의했으나 제시문에서 'ElectricEngine 타입의 Engine 을 사용해야합니다.' 라는 언급이 있어 클래스로 바꾸었습니다. @@ -98,7 +98,7 @@ class HybridCar: Car { `Car` 클래스의 `engine` 변수는 `Engine`타입이므로 메소드를 사용하기 위해 `HydrogenEngine`으로 다운캐스팅 해주었습니다. -### 2) +### 2) 제네릭 구조체 기존에는 구조체 자체에서 제네릭 타입에 프로토콜을 제한했습니다. ```swift From 5f1176759a9e3232e29521cbfacbb87502d265e7 Mon Sep 17 00:00:00 2001 From: Bambu Date: Fri, 9 Jan 2026 09:58:48 +0900 Subject: [PATCH 16/26] =?UTF-8?q?Feat:=20=EB=8F=84=EC=A0=84=20=EB=AC=B8?= =?UTF-8?q?=EC=A0=9C=203=20=EA=B5=AC=ED=98=84=20=EC=99=84=EB=A3=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ch.2/ch.2/main.swift" | 13 ++++++ ...\240\204 \353\254\270\354\240\234 3.swift" | 41 +++++++++++++++++++ 2 files changed, 54 insertions(+) create mode 100644 "\353\263\200\354\230\210\353\246\260/ch.2/ch.2/\353\217\204\354\240\204 \352\263\274\354\240\234/\353\217\204\354\240\204 \353\254\270\354\240\234 3.swift" diff --git "a/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/main.swift" "b/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/main.swift" index bfd803c..9b1cfeb 100644 --- "a/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/main.swift" +++ "b/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/main.swift" @@ -121,3 +121,16 @@ print(comparableBox.items) var incomparableBox = SortableBox(items: [electric, hybrid]) // T: Car // incomparableBox.sortItems() // 컴파일 에러 발생 + + +// 3. +// - 기본 introduce() 동작 +let test = Test() +print(test.introduce()) + +// - Robot, Cat, Dog 타입의 커스텀 동작 +print(""" +\(Dog(name: "뽀삐").introduce()) +\(Cat(name: "삐용").introduce()) +\(Robot2(name: "메칸더V").introduce()) +""") diff --git "a/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/\353\217\204\354\240\204 \352\263\274\354\240\234/\353\217\204\354\240\204 \353\254\270\354\240\234 3.swift" "b/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/\353\217\204\354\240\204 \352\263\274\354\240\234/\353\217\204\354\240\204 \353\254\270\354\240\234 3.swift" new file mode 100644 index 0000000..e985cba --- /dev/null +++ "b/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/\353\217\204\354\240\204 \352\263\274\354\240\234/\353\217\204\354\240\204 \353\254\270\354\240\234 3.swift" @@ -0,0 +1,41 @@ +// +// 도전 문제 3.swift +// ch.2 +// +// Created by 변예린 on 1/9/26. +// + +import Foundation + +extension Introducible { + func introduce() -> String { + return "안녕하세요, 저는 \(name)입니다." + } +} + +struct Test: Introducible { + var name = "Test" +} + +struct Robot2: Introducible { + var name: String { + didSet { // 변경될 때마다 변경 이전값, 이후값 출력 + if oldValue != name { + print(""" + name 변경 알림 + 변경 이전 값: \(oldValue) + 변경 이후 값: \(name) + """) + } + } + } + + func introduce() -> String { + return "삐빅- 저는 \(name)입니다." + } + + // 고유 메서드 + func batteryCharge() { + print("배터리 충전중...") + } +} From bb9f36ea038f1438247d6499601216d0df42bbfd Mon Sep 17 00:00:00 2001 From: Bambu Date: Fri, 9 Jan 2026 12:16:55 +0900 Subject: [PATCH 17/26] =?UTF-8?q?Feat:=20=EB=8F=84=EC=A0=84=20=EB=AC=B8?= =?UTF-8?q?=EC=A0=9C=204=20=EA=B5=AC=ED=98=84=20=EC=99=84=EB=A3=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 92 +++++++++++++++++++ .../ch.2/ch.2/main.swift" | 26 ++++++ ...\240\204 \353\254\270\354\240\234 4.swift" | 37 ++++++++ 3 files changed, 155 insertions(+) create mode 100644 "\353\263\200\354\230\210\353\246\260/ch.2/ch.2/\353\217\204\354\240\204 \352\263\274\354\240\234/\353\217\204\354\240\204 \353\254\270\354\240\234 4.swift" diff --git a/README.md b/README.md index 0fe4b79..7b6d936 100644 --- a/README.md +++ b/README.md @@ -134,3 +134,95 @@ extension SortableBox where T: Comparable { → 타입 T가 `Comparable`을 준수하지 않으면 `sortItems()` 메소드는 보이지 않습니다. 위 패턴은 매우 다양하게 사용될 수 있으므로 꼭 기억해두겠습니다! + +### 4) 순환 참조 +**⚠️ 순환 참조 생성시 발견한 사소한(?) 오류** + +```swift +var a: A? +var b: B? + +a = A(name: "personA", home: nil) +b = B(name: "apartmentB", tenant: nil) + +a?.home = b +b?.tenant = a + +a = nil +b = nil +``` +→ 의도한 대로 순환참조 발생 + +```swift +var a: A? = A(name: "personA", home: b) +var b: B? = B(name: "B", tenant: a) + +a = nil +b = nil +``` +→ `a`와 `b` 모두 메모리에서 해제됨 + +**🧐 둘다 동일한 방법으로 생성한 객체인데 왜 아래 방법은 메모리에서 해제되는가?** + +➡︎ ❗️ 두 번째 방법은 애초에 잘못된 코드였어요!! + +```swift +var a: A? = A(name: "personA", home: b) +``` + +→ `a`를 생성하는 시점에 `b`는 없습니다. 그래서 원래는 여기에서 오류가 나야하는데,, 탑레벨에서는 이유는 모르겠지만 오류가 나지않고 빌드가 됩니다... (함수에 넣어보면 오류가 발생합니다.) + +이때 `a.home`을 찍어보면 `nil`값으로 출력됩니다. + +즉, 애초에 `a`는 `b`를 참조하고 있지 않았던 것이죠. + +다음으로 생성된 `b`에서는 `a`를 참조하지만 `a`가 `nil`값으로 먼저 해제되기 때문에 `a`와 `b` 사이에 순환 참조가 발생하지 않았던 것이었습니다. + +실무에서는 이런 코드를 작성할 일 자체가 없을 것이라고 하셨지만.. 잘 살펴봐야겠습니다😵 + +**⚠️ 순환 참조 생성시 있었던 이상한 점..** + +위에서 있었던 작은 해프닝을 뒤로 하고 클로저의 순환 참조를 만들고 있었는데 제대로 구현한 것 같은데 또 메모리에서 해제가 되었습니다. + +```swift +var a: A? +var b: B? + +func circularRef() { + a = A(name: "personA", home: nil) + b = B(name: "apartmentB", tenant: nil) + + a?.home = b + b?.tenant = a + + b?.closure = { + print("\(a?.name)") + } +} + +circularRef() + +a = nil +b = nil +``` + +위에서 언급한 오류를 피하기 위해 인스턴스 선언과 `nil` 할당 외에는 함수 내에서 구현하였는데, 순환 참조가 생성되지 않고 계속 메모리에서 해제되었습니다. + +다만 `nil`할당을 없애고 코드 내에서 인스턴스를 선언 하였더니 순환 참조가 생성되었습니다. + +```swift +func circularRef() { + var a: A? + var b: B? + + ... + +} + +circularRef() +``` +→ 함수 내에서 인스턴스를 선언했기 때문에 함수의 실행이 종료되면 자동적으로 두 인스턴스가 사라집니다. 따라서 따로 `nil`값을 할당해줄 필요가 없습니다. + +이렇게 해결하긴 했지만.. 튜터님 말씀으로는 탑레벨에서 인스턴스에 직접 `nil`값을 할당해줄 때 컴파일러 내부에서 ARC에 관한 동작이 우리가 생각하는 것과는 다르게 흘러가는 듯하다고 합니다. + +좀더 조예가 깊어지면 알아봐야겠습니다... diff --git "a/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/main.swift" "b/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/main.swift" index 9b1cfeb..e15b588 100644 --- "a/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/main.swift" +++ "b/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/main.swift" @@ -134,3 +134,29 @@ print(""" \(Cat(name: "삐용").introduce()) \(Robot2(name: "메칸더V").introduce()) """) + + +// 4. +// - 순환 참조 발생 및 해결하기 +func circularRef() { + var a: A? + var b: B? + + a = A(name: "personA", home: nil) + b = B(name: "apartmentB", tenant: nil) + + a?.home = b + b?.tenant = a + + // 클로저로 인한 순환 참조 발생 +// b?.closure = { +// print("\(a?.name)") +// } + + // 클로저 순환 참조 해결 + b?.closure = { [weak a] in + print("\(a?.name)") + } +} + +circularRef() diff --git "a/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/\353\217\204\354\240\204 \352\263\274\354\240\234/\353\217\204\354\240\204 \353\254\270\354\240\234 4.swift" "b/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/\353\217\204\354\240\204 \352\263\274\354\240\234/\353\217\204\354\240\204 \353\254\270\354\240\234 4.swift" new file mode 100644 index 0000000..d766da3 --- /dev/null +++ "b/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/\353\217\204\354\240\204 \352\263\274\354\240\234/\353\217\204\354\240\204 \353\254\270\354\240\234 4.swift" @@ -0,0 +1,37 @@ +// +// 도전 문제 4.swift +// ch.2 +// +// Created by 변예린 on 1/9/26. +// + +import Foundation + +class A { + let name: String + var home: B? + + init(name: String, home: B?) { + self.name = name + self.home = home + } + + deinit { + print("\(name)가 메모리에서 해제되었습니다.") + } +} + +class B { + let name: String + weak var tenant: A? // var tenant: A? 로 작성 시 순환참조 발생 + var closure: (() -> Void)? + + init(name: String, tenant: A?) { + self.name = name + self.tenant = tenant + } + + deinit { + print("\(name)가 메모리에서 해제되었습니다.") + } +} From e8845bd351cd6f1224c0f70d328eac3779718568 Mon Sep 17 00:00:00 2001 From: Bambu Date: Fri, 9 Jan 2026 14:04:54 +0900 Subject: [PATCH 18/26] =?UTF-8?q?Chore:=20Read=20me=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 4 ++-- ...\355\225\204\354\210\230 \353\254\270\354\240\234 4.swift" | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 7b6d936..4fbd0b7 100644 --- a/README.md +++ b/README.md @@ -223,6 +223,6 @@ circularRef() ``` → 함수 내에서 인스턴스를 선언했기 때문에 함수의 실행이 종료되면 자동적으로 두 인스턴스가 사라집니다. 따라서 따로 `nil`값을 할당해줄 필요가 없습니다. -이렇게 해결하긴 했지만.. 튜터님 말씀으로는 탑레벨에서 인스턴스에 직접 `nil`값을 할당해줄 때 컴파일러 내부에서 ARC에 관한 동작이 우리가 생각하는 것과는 다르게 흘러가는 듯하다고 합니다. +~~이렇게 해결하긴 했지만.. 튜터님 말씀으로는 탑레벨에서 인스턴스에 직접 `nil`값을 할당해줄 때 컴파일러 내부에서 ARC에 관한 동작이 우리가 생각하는 것과는 다르게 흘러가는 듯하다고 합니다.~~ -좀더 조예가 깊어지면 알아봐야겠습니다... +⇒ 탑레벨에서 전역변수로 선언될 때는! `a`가 아니라 (예시)Global이라는 전역변수가 담긴 무언가를 참조한다고 합니다! (실제로는 어디에 담기는지는 모르겠지만) 그래서 `a` 인스턴스 자체에는 참조 카운트가 올라가지 않기 때문에 `a = nil`을 할당해주었을 때 메모리에서 해제가 된다고 합니다!! diff --git "a/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/\355\225\204\354\210\230 \352\265\254\355\230\204 \352\263\274\354\240\234/\355\225\204\354\210\230 \353\254\270\354\240\234 4.swift" "b/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/\355\225\204\354\210\230 \352\265\254\355\230\204 \352\263\274\354\240\234/\355\225\204\354\210\230 \353\254\270\354\240\234 4.swift" index c9ba10b..0c8c0a2 100644 --- "a/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/\355\225\204\354\210\230 \352\265\254\355\230\204 \352\263\274\354\240\234/\355\225\204\354\210\230 \353\254\270\354\240\234 4.swift" +++ "b/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/\355\225\204\354\210\230 \352\265\254\355\230\204 \352\263\274\354\240\234/\355\225\204\354\210\230 \353\254\270\354\240\234 4.swift" @@ -41,7 +41,7 @@ struct Robot: Introducible { // Cat 타입 정의 struct Cat: Introducible { var name: String - + func introduce() -> String { return "야옹, 저는 \(name)입니다." } From 87184874d6f980c65f5c8a981b830503ce7e1988 Mon Sep 17 00:00:00 2001 From: Bambu Date: Fri, 9 Jan 2026 14:08:47 +0900 Subject: [PATCH 19/26] =?UTF-8?q?Chore:=20Read=20Me=20=EC=88=98=EC=A0=95?= =?UTF-8?q?=20-=20=EC=98=88=EC=8B=9C=20=EC=BD=94=EB=93=9C=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/README.md b/README.md index af816b3..30fce97 100644 --- a/README.md +++ b/README.md @@ -227,3 +227,23 @@ circularRef() ~~이렇게 해결하긴 했지만.. 튜터님 말씀으로는 탑레벨에서 인스턴스에 직접 `nil`값을 할당해줄 때 컴파일러 내부에서 ARC에 관한 동작이 우리가 생각하는 것과는 다르게 흘러가는 듯하다고 합니다.~~ ⇒ 탑레벨에서 전역변수로 선언될 때는! `a`가 아니라 (예시)Global이라는 전역변수가 담긴 무언가를 참조한다고 합니다! (실제로는 어디에 담기는지는 모르겠지만) 그래서 `a` 인스턴스 자체에는 참조 카운트가 올라가지 않기 때문에 `a = nil`을 할당해주었을 때 메모리에서 해제가 된다고 합니다!! + +```swift +var a: A? +var b: B? + +func circularRef() { + a = A(name: "personA", home: nil) + b = B(name: "apartmentB", tenant: nil) + + a?.home = b + b?.tenant = a + + + b?.closure = { [a] in // a를 참조하도록 명시 + print("\(a?.name)") + } + +} +``` +➡︎ 그래서 이렇게 클로저 내에서 `[a]`를 추가하여 `a` 인스턴스를 참조하도록 직접 명시하면 순환 참조가 발생합니다. From 7ee2994a4359688237e183ce603c620eaae0b9d9 Mon Sep 17 00:00:00 2001 From: Bambu Date: Fri, 9 Jan 2026 17:18:47 +0900 Subject: [PATCH 20/26] =?UTF-8?q?Chore:=20=ED=95=84=EC=88=98=20=EB=AC=B8?= =?UTF-8?q?=EC=A0=9C=204=20=EA=B5=AC=EC=A1=B0=EC=B2=B4=20->=20=ED=81=B4?= =?UTF-8?q?=EB=9E=98=EC=8A=A4=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...4\240\204 \353\254\270\354\240\234 3.swift" | 6 +++++- ...4\210\230 \353\254\270\354\240\234 4.swift" | 18 +++++++++++++++--- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git "a/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/\353\217\204\354\240\204 \352\263\274\354\240\234/\353\217\204\354\240\204 \353\254\270\354\240\234 3.swift" "b/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/\353\217\204\354\240\204 \352\263\274\354\240\234/\353\217\204\354\240\204 \353\254\270\354\240\234 3.swift" index e985cba..32d3ddb 100644 --- "a/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/\353\217\204\354\240\204 \352\263\274\354\240\234/\353\217\204\354\240\204 \353\254\270\354\240\234 3.swift" +++ "b/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/\353\217\204\354\240\204 \352\263\274\354\240\234/\353\217\204\354\240\204 \353\254\270\354\240\234 3.swift" @@ -17,7 +17,7 @@ struct Test: Introducible { var name = "Test" } -struct Robot2: Introducible { +class Robot2: Introducible { var name: String { didSet { // 변경될 때마다 변경 이전값, 이후값 출력 if oldValue != name { @@ -30,6 +30,10 @@ struct Robot2: Introducible { } } + init(name: String) { + self.name = name + } + func introduce() -> String { return "삐빅- 저는 \(name)입니다." } diff --git "a/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/\355\225\204\354\210\230 \352\265\254\355\230\204 \352\263\274\354\240\234/\355\225\204\354\210\230 \353\254\270\354\240\234 4.swift" "b/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/\355\225\204\354\210\230 \352\265\254\355\230\204 \352\263\274\354\240\234/\355\225\204\354\210\230 \353\254\270\354\240\234 4.swift" index 0c8c0a2..bb64ff0 100644 --- "a/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/\355\225\204\354\210\230 \352\265\254\355\230\204 \352\263\274\354\240\234/\355\225\204\354\210\230 \353\254\270\354\240\234 4.swift" +++ "b/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/\355\225\204\354\210\230 \352\265\254\355\230\204 \352\263\274\354\240\234/\355\225\204\354\210\230 \353\254\270\354\240\234 4.swift" @@ -15,7 +15,7 @@ protocol Introducible { } // Robot 타입 정의 -struct Robot: Introducible { +class Robot: Introducible { var name: String { didSet { // 변경될 때마다 변경 이전값, 이후값 출력 if oldValue != name { @@ -28,6 +28,10 @@ struct Robot: Introducible { } } + init(name: String) { + self.name = name + } + func introduce() -> String { return "안녕하세요, 저는 \(name)입니다." } @@ -39,9 +43,13 @@ struct Robot: Introducible { } // Cat 타입 정의 -struct Cat: Introducible { +class Cat: Introducible { var name: String + init(name: String) { + self.name = name + } + func introduce() -> String { return "야옹, 저는 \(name)입니다." } @@ -53,9 +61,13 @@ struct Cat: Introducible { } // Dog 타입 정의 -struct Dog: Introducible { +class Dog: Introducible { var name: String + init(name: String) { + self.name = name + } + func introduce() -> String { return "멍멍! 저는 \(name)입니다." } From b954c66897bfcb06543fb2cf2ef3d938b6442ca4 Mon Sep 17 00:00:00 2001 From: Bambu Date: Fri, 9 Jan 2026 17:30:49 +0900 Subject: [PATCH 21/26] =?UTF-8?q?Chore:=20=ED=95=84=EC=88=98=20=EB=AC=B8?= =?UTF-8?q?=EC=A0=9C=204=20=ED=94=84=EB=A1=9C=ED=86=A0=EC=BD=9C=20?= =?UTF-8?q?=EC=86=8D=EC=84=B1=20=EC=84=A0=EC=96=B8=EB=B6=80=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../\355\225\204\354\210\230 \353\254\270\354\240\234 4.swift" | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git "a/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/\355\225\204\354\210\230 \352\265\254\355\230\204 \352\263\274\354\240\234/\355\225\204\354\210\230 \353\254\270\354\240\234 4.swift" "b/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/\355\225\204\354\210\230 \352\265\254\355\230\204 \352\263\274\354\240\234/\355\225\204\354\210\230 \353\254\270\354\240\234 4.swift" index bb64ff0..f12cfe0 100644 --- "a/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/\355\225\204\354\210\230 \352\265\254\355\230\204 \352\263\274\354\240\234/\355\225\204\354\210\230 \353\254\270\354\240\234 4.swift" +++ "b/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/\355\225\204\354\210\230 \352\265\254\355\230\204 \352\263\274\354\240\234/\355\225\204\354\210\230 \353\254\270\354\240\234 4.swift" @@ -9,7 +9,7 @@ import Foundation // 프로토콜 정의 protocol Introducible { - var name: String { get } + var name: String { get set } func introduce() -> String } From 5214aa09daaccffab00d49198b41497a0af5cc37 Mon Sep 17 00:00:00 2001 From: Bambu Date: Fri, 9 Jan 2026 17:34:38 +0900 Subject: [PATCH 22/26] =?UTF-8?q?Chore:=20=EC=A0=91=EA=B7=BC=20=EC=A0=9C?= =?UTF-8?q?=EC=96=B4=EC=9E=90=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...53\217\204\354\240\204 \353\254\270\354\240\234 1.swift" | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git "a/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/\353\217\204\354\240\204 \352\263\274\354\240\234/\353\217\204\354\240\204 \353\254\270\354\240\234 1.swift" "b/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/\353\217\204\354\240\204 \352\263\274\354\240\234/\353\217\204\354\240\204 \353\254\270\354\240\234 1.swift" index 6bd9fe4..6e41a2d 100644 --- "a/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/\353\217\204\354\240\204 \352\263\274\354\240\234/\353\217\204\354\240\204 \353\254\270\354\240\234 1.swift" +++ "b/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/\353\217\204\354\240\204 \352\263\274\354\240\234/\353\217\204\354\240\204 \353\254\270\354\240\234 1.swift" @@ -23,15 +23,15 @@ class Car { } // 접근 제어자와 함께 동작 정의 - public func drive() { + internal func drive() { print("[\(brand) \(model)] 주행 중...") } - public func stop() { + internal func stop() { print("[\(brand) \(model)] 정지") } - public func park() { + internal func park() { print("[\(brand) \(model)] 주차") } } From 053f57f517b4a2d0852f9c1bad41e81cd5c7a92b Mon Sep 17 00:00:00 2001 From: Bambu Date: Mon, 12 Jan 2026 19:23:13 +0900 Subject: [PATCH 23/26] =?UTF-8?q?Chore:=20=ED=95=84=EC=88=98=20=EB=AC=B8?= =?UTF-8?q?=EC=A0=9C=203=20=EC=88=98=EC=A0=95=20-=20filter=20=EA=B3=A0?= =?UTF-8?q?=EC=B0=A8=ED=95=A8=EC=88=98=20=EB=82=B4=20=EC=A1=B0=EA=B1=B4=20?= =?UTF-8?q?=EC=88=98=EC=A0=95=20/=20d=20=ED=95=A8=EC=88=98=20=EC=A0=9C?= =?UTF-8?q?=EB=84=A4=EB=A6=AD=20=ED=83=80=EC=9E=85=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...\204\354\210\230 \353\254\270\354\240\234 3.swift" | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git "a/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/\355\225\204\354\210\230 \352\265\254\355\230\204 \352\263\274\354\240\234/\355\225\204\354\210\230 \353\254\270\354\240\234 3.swift" "b/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/\355\225\204\354\210\230 \352\265\254\355\230\204 \352\263\274\354\240\234/\355\225\204\354\210\230 \353\254\270\354\240\234 3.swift" index b927e92..22bed52 100644 --- "a/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/\355\225\204\354\210\230 \352\265\254\355\230\204 \352\263\274\354\240\234/\355\225\204\354\210\230 \353\254\270\354\240\234 3.swift" +++ "b/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/\355\225\204\354\210\230 \352\265\254\355\230\204 \352\263\274\354\240\234/\355\225\204\354\210\230 \353\254\270\354\240\234 3.swift" @@ -11,28 +11,29 @@ struct Required3 { // Int 배열 짝수번째 요소 제거하여 반환 func a (_ arr: [Int]) -> [Int] { return arr.enumerated() - .filter { $0.offset % 2 != 0 } + .filter { !$0.offset.isMultiple(of: 2) } .map { $0.element } } // String 배열 짝수번째 요소 제거하여 반환 func b (_ arr: [String]) -> [String] { return arr.enumerated() - .filter { $0.offset % 2 != 0 } + .filter { !$0.offset.isMultiple(of: 2) } .map { $0.element } } // 두 함수 a, b를 대체하는 함수 func c (_ arr: [T]) -> [T] { return arr.enumerated() - .filter { $0.offset % 2 != 0 } + .filter { !$0.offset.isMultiple(of: 2) } .map { $0.element } } // Numeric 프로토콜을 준수하는 타입을 파라미터로 받는 함수 - func d (_ arr: [D]) -> [D] { + // - 새로운 타입으로 선언할 필요가 없어 T 타입 재사용 + func d (_ arr: [T]) -> [T] { return arr.enumerated() - .filter { $0.offset % 2 != 0 } + .filter { !$0.offset.isMultiple(of: 2) } .map { $0.element } } } From 0732ad5e4c19bca8f58a41aae7de9e74bf26e717 Mon Sep 17 00:00:00 2001 From: Bambu Date: Mon, 12 Jan 2026 19:36:01 +0900 Subject: [PATCH 24/26] =?UTF-8?q?Chore:=20=ED=95=84=EC=88=98=20=EB=AC=B8?= =?UTF-8?q?=EC=A0=9C=204=20=EA=B3=A0=EC=9C=A0=20=EB=A9=94=EC=84=9C?= =?UTF-8?q?=EB=93=9C=20=ED=98=B8=EC=B6=9C=EB=AC=B8=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ch.2/ch.2/main.swift" | 39 +++++++++++++------ 1 file changed, 27 insertions(+), 12 deletions(-) diff --git "a/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/main.swift" "b/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/main.swift" index e15b588..e7a0885 100644 --- "a/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/main.swift" +++ "b/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/main.swift" @@ -55,22 +55,37 @@ introducibleArr.append(robot) introducibleArr.append(Cat(name: "고양이")) introducibleArr.append(Dog(name: "강아지")) -for element in introducibleArr { - if element is Robot { - let instance = element as? Robot - instance?.batteryCharge() - } else if element is Cat { - let instance = element as? Cat - instance?.meow() - } else if element is Dog { - let instance = element as? Dog - instance?.bark() - } else { - continue +// 기존 풀이 +//for element in introducibleArr { +// if element is Robot { +// let instance = element as? Robot +// instance?.batteryCharge() +// } else if element is Cat { +// let instance = element as? Cat +// instance?.meow() +// } else if element is Dog { +// let instance = element as? Dog +// instance?.bark() +// } else { +// continue +// } +//} + +// 수정 - 타입캐스팅과 옵셔널 바인딩을 한번에 작성하여 코드 수를 줄임 +// - 옵셔널 바인딩을 사용하여 옵셔널 없이 타입을 사용 가능 +introducibleArr.forEach { + if let robot = $0 as? Robot { + robot.batteryCharge() + } else if let cat = $0 as? Cat { + cat.meow() + } else if let dog = $0 as? Dog { + dog.bark() } } + + // 5. // - throwing function 호출 do { From 13a61c8d0cae40087f25116b630d53eb30746a08 Mon Sep 17 00:00:00 2001 From: Bambu Date: Mon, 12 Jan 2026 20:05:10 +0900 Subject: [PATCH 25/26] =?UTF-8?q?Chore:=20=EC=A3=BC=EC=84=9D=20=EB=B0=8F?= =?UTF-8?q?=20=EC=B6=9C=EB=A0=A5=20=EC=98=88=EC=8B=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ch.2/ch.2/main.swift" | 2 +- ...204\354\210\230 \353\254\270\354\240\234 3.swift" | 12 ++++++++++-- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git "a/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/main.swift" "b/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/main.swift" index e7a0885..9ea851f 100644 --- "a/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/main.swift" +++ "b/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/main.swift" @@ -39,7 +39,7 @@ print(Required3().c(["가", "나", "다", "라", "마"])) // - 함수 d 호출 코드 // print(answer.required3.d(["가"])) // 오류 -print(Required3().d([1, 2, 3, 4, 5])) +print(Required3().d([1.3, 2.5, 3.0, 4.6, 5.6])) // 4. diff --git "a/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/\355\225\204\354\210\230 \352\265\254\355\230\204 \352\263\274\354\240\234/\355\225\204\354\210\230 \353\254\270\354\240\234 3.swift" "b/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/\355\225\204\354\210\230 \352\265\254\355\230\204 \352\263\274\354\240\234/\355\225\204\354\210\230 \353\254\270\354\240\234 3.swift" index 22bed52..af77354 100644 --- "a/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/\355\225\204\354\210\230 \352\265\254\355\230\204 \352\263\274\354\240\234/\355\225\204\354\210\230 \353\254\270\354\240\234 3.swift" +++ "b/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/\355\225\204\354\210\230 \352\265\254\355\230\204 \352\263\274\354\240\234/\355\225\204\354\210\230 \353\254\270\354\240\234 3.swift" @@ -8,7 +8,14 @@ import Foundation struct Required3 { + // func a (_ arr: [Int]) -> [Int] { << 기존 코드 + // return arr.enumerated() + // .filter { $0.offset % 2 != 0) } + // .map { $0.element } + // } + // Int 배열 짝수번째 요소 제거하여 반환 + // - filter 조건 수정 : 조건을 좀더 명확히 보이게 하기 위해 func a (_ arr: [Int]) -> [Int] { return arr.enumerated() .filter { !$0.offset.isMultiple(of: 2) } @@ -30,10 +37,11 @@ struct Required3 { } // Numeric 프로토콜을 준수하는 타입을 파라미터로 받는 함수 - // - 새로운 타입으로 선언할 필요가 없어 T 타입 재사용 + // - 굳이 다른 타입 이름을 사용할 필요가 없어 T로 수정 func d (_ arr: [T]) -> [T] { return arr.enumerated() .filter { !$0.offset.isMultiple(of: 2) } .map { $0.element } - } + } + } From 5d43b0babd79d98145e0b582434b0d4b319b6639 Mon Sep 17 00:00:00 2001 From: Bambu Date: Tue, 20 Jan 2026 20:38:26 +0900 Subject: [PATCH 26/26] =?UTF-8?q?Chore:=20=ED=8A=9C=ED=84=B0=EB=8B=98=20?= =?UTF-8?q?=ED=94=BC=EB=93=9C=EB=B0=B1=20=EB=B0=98=EC=98=81=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ch.2/ch.2/main.swift" | 14 ++++++++++++++ ...4\354\240\204 \353\254\270\354\240\234 1.swift" | 2 +- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git "a/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/main.swift" "b/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/main.swift" index 9ea851f..0a5a5c4 100644 --- "a/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/main.swift" +++ "b/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/main.swift" @@ -83,6 +83,20 @@ introducibleArr.forEach { } } +// - 튜터님 피드백 switch문: 옵셔널 바인딩하면서 다운캐스팅 -- 바로 고유메서드 사용 가능 +// default case를 통해 추후 새로운 타입 추가시 적절한 처리 가능 +introducibleArr.forEach { + switch $0 { + case let robot as Robot: + robot.batteryCharge() + case let cat as Cat: + cat.meow() + case let dog as Dog: + dog.bark() + default: + break + } +} diff --git "a/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/\353\217\204\354\240\204 \352\263\274\354\240\234/\353\217\204\354\240\204 \353\254\270\354\240\234 1.swift" "b/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/\353\217\204\354\240\204 \352\263\274\354\240\234/\353\217\204\354\240\204 \353\254\270\354\240\234 1.swift" index 6e41a2d..d3c66be 100644 --- "a/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/\353\217\204\354\240\204 \352\263\274\354\240\234/\353\217\204\354\240\204 \353\254\270\354\240\234 1.swift" +++ "b/\353\263\200\354\230\210\353\246\260/ch.2/ch.2/\353\217\204\354\240\204 \352\263\274\354\240\234/\353\217\204\354\240\204 \353\254\270\354\240\234 1.swift" @@ -65,7 +65,7 @@ enum EngineType { // Engine 커스텀 타입 정의 class Engine { - var type: EngineType + let type: EngineType init(_ type: EngineType) { self.type = type