Swift 과제물

iOS 프로그래밍 6주차 Report

Dreaming Developer Student 2023. 10. 17. 09:41
728x90
반응형
SMALL
1급 객체 예제소스 
func up(num: Int) -> Int {
return num + 1
}
func down(num: Int) -> Int {
return num - 1
}
print(type(of:up))
let toUp = up
print(type(of:toUp))
print(up(num:10))
print(toUp(10))
let toDown = down

 

func upDown(Fun: (Int) -> Int, value: Int) {
let result = Fun(value)
print("결과 = \(result)")
}
upDown(Fun:toUp, value: 10) //toUp(10)
upDown(Fun:toDown, value: 10) //toDown(10)
func decideFun(x: Bool) -> (Int) -> Int {
//매개변수형 리턴형이 함수형
if x {
return toUp
} else {
return toDown
}
}
let r = decideFun(x:true) // let r = toUp
print(type(of:r)) //(Int) -> Int
print(r(10)) // toUp(10)
func up(num: Int) -> Int {
return num + 1
}
func down(num: Int) -> Int {
return num - 1
}
print(type(of:up))
let toUp = up
print(type(of:toUp))
print(up(num:10))
print(toUp(10))
let toDown = down
func upDown(Fun: (Int) -> Int, value: Int) {
let result = Fun(value)
print("결과 = \(result)")
}
upDown(Fun:toUp, value: 10) //toUp(10)
upDown(Fun:toDown, value: 10) //toDown(10)
func decideFun(x: Bool) -> (Int) -> Int {
//매개변수형 리턴형이 함수형
if x {
return toUp
} else {
return toDown
}
}
let r = decideFun(x:true) // let r = toUp
print(type(of:r)) //(Int) -> Int
print(r(10)) // toUp(10)
클로저 함수 예제소스

 

func add(x: Int, y: Int) -> Int {
return(x+y)
}
print(add(x:10, y:20))
let add1 = {(x: Int, y: Int) -> Int in //클로저 함수
return(x+y)
}
print(add1(x:10, y:20))

 Error Message : main.swift:8:11: error: extraneous argument labels 'x:y:' in call
print(add1(x:10, y:20))

- >  필요없는 argument label을 써서 오류가 발생 

 

함수를 호출할때는  argument label이 필요가 없다.

 

오류 수정 소스

 

func add(x: Int, y: Int) -> Int {
return(x+y)
}
print(add(x:10, y:20))
let add1 = {(x: Int, y: Int) -> Int in //클로저 함수
return(x+y)
}
print(add1(10,20))

클로저는 함수와 그 함수가 선언됐을 때의 렉시컬 환경(Lexical Environment)과의 조합입니다. 이렇게 클로저를 지원하는 언어는 여러 가지가 있습니다:

  1. JavaScript: JavaScript에서 클로저는 함수와 그 함수가 선언된 렉시컬 스코프의 조합으로 이루어집니다.
javascript
function outer() {
    let count = 0;
    return function inner() {
        count += 1;
        return count;
    };
}
let increment = outer();
console.log(increment()); // 출력: 1
console.log(increment()); // 출력: 2
  1. Python: Python에서도 클로저를 만들 수 있습니다.
python
def outer():
    count = 0
    def inner():
        nonlocal count
        count += 1
        return count
    return inner

increment = outer()
print(increment()) # 출력: 1
print(increment()) # 출력: 2 
  1. Swift: Swift 역시 클로저를 지원합니다.
swift
var counter: () -> Int {
    var count = 0;
    return {
        count += 1;
        return count;
    }
}
let increment = counter()
print(increment()) // 출력: Optional(1)
print(increment()) // 출력: Optional(2)
  1. Ruby: Ruby에서도 블록, Proc 객체, 람다 등을 통해 클로저를 구현할 수 있습니다.
  2. Groovy: Groovy에서는 {} 안에 코드를 넣어서 클로저를 생성할 수 있습니다.
  3. Scala, Kotlin 등 JVM 기반 언어들 역시 익명 함수나 람다 표현식을 통해 클로저 기능을 제공합니다.

이 외에도 많은 현대 프로그래밍 언어들이 비슷한 방식으로 클로저 기능을 제공하고 있으니 필요한 언어의 문법 가이드나 참조 문서에서 확인해보시면 좋겠습니다!

 
후행 클로저(traliing closure)
func mul(a: Int, b: Int) -> Int {
return a * b
}
let multiply = {(a: Int, b: Int) -> Int in
return a * b
}
print(mul(a:10, b:20))
print(multiply(10, 20))
let add = {(a: Int, b: Int) -> Int in
return a + b
}
print(add(10, 20))
func math(x: Int, y: Int, cal: (Int, Int) -> Int) -> Int {
return cal(x, y)
}
var result = math(x: 10, y: 20, cal: add) //return add(10,20)
print(result)
result = math(x: 10, y: 20, cal: {(a: Int, b: Int) -> Int in
return a + b
}) //add 에 클로저 함수를 넣을 수 있다.
print(result)
result = math(x: 10, y: 20) {(a: Int, b: Int) -> Int in
return a + b

 

} //trailing closure : 소괄호 외부에다 작성할 수 있다.

 

print(result)

클로저가 함수의 마지막 argument라면 마지막 매개변수명(cal)을 생략한 후 함수 소괄호 외부에 클로저를 작성 할 수있다.

 

후행 클로저(Trailing Closure)는 함수의 마지막 인자로 전달되는 클로저를 함수의 괄호 밖에 작성하는 문법을 말합니다. 이는 주로 Swift 언어에서 사용됩니다.

Swift에서 후행 클로저는 읽기 쉽고, 더 명확한 코드를 작성할 수 있게 도와줍니다. 특히, 클로저의 본문이 길거나 해당 함수의 유일한 인자일 경우에 자주 사용됩니다.

다음은 후행 클로저를 사용하는 예시입니다:

swift
let numbers = [1, 2, 3, 4, 5]

// map 메서드에 후행 클로저를 사용하여 각 요소를 제곱하는 연산을 수행합니다.
let squaredNumbers = numbers.map { number in
    return number * number
}
print(squaredNumbers) // 출력: [1, 4, 9, 16, 25]

위 코드에서 map 메서드는 하나의 인자만 받습니다. 그 인자가 바로 우리가 제공한 클로저입니다. 이처럼 하나의 인자만 받아들이며 그것이 클로저인 경우 후행클로져(trailing closure) 문법을 활용할 수 있습니다.

클로져가 길거나 복잡하다면 후행 클로저 문법을 사용함으로써 가독성을 높일 수 있습니다.

 

클로저의 축약 표현 소스 
func mul(a: Int, b: Int) -> Int {
return a * b
}
let multiply = {(a: Int, b: Int) -> Int in
return a * b
}
print(mul(a:10, b:20))
print(multiply(10, 20))
let add = {(a: Int, b: Int) -> Int in
return a + b
}
print(add(10, 20))
func math(x: Int, y: Int, cal: (Int, Int) -> Int) -> Int {
return cal(x, y)
}
var result = math(x: 10, y: 20, cal: add) //return add(10,20)
print(result)
result = math(x: 10, y: 20, cal: { in //리턴형을 생략할 수 있다.
return a + b
}) //add 에 클로저 함수를 넣을 수 있다.
print(result)
result = math(x: 10, y: 20) {(a: Int, b: Int) -> Int in
return a + b
} //trailing closure
print(result)
 
 
 
클로저의 축약 표현 소스  수정 

 

func mul(a: Int, b: Int) -> Int {

 

return a * b
}
let multiply = {(a: Int, b: Int) -> Int in
return a * b
}
print(mul(a:10, b:20))
print(multiply(10, 20))
let add = {(a: Int, b: Int) -> Int in
return a + b
}
print(add(10, 20))
func math(x: Int, y: Int, cal: (Int, Int) -> Int) -> Int {
return cal(x, y)
}
var result = math(x: 10, y: 20, cal: add) //return add(10,20)
print(result)
result = math(x: 10, y: 20, cal: { $0 + $1}) //리턴형을 생략할 수 있다.
//add 에 클로저 함수를 넣을 수 있다.
print(result)

 

result = math(x: 10, y: 20) { $0 + $1} // 매개변수를 생략하고 리턴할 수 있다 (단축인자 사용) shorthand argument name

-

//trailing closure

 

print(result)

클로저(Closure)는 함수가 자유 변수에 대한 참조를 유지하는 것을 말합니다. 일반적으로 클로저는 함수가 선언된 렉시컬 환경(lexical environment)을 기억하고, 해당 렉시컬 환경 밖에서 호출되더라도 그 환경에 대한 접근을 제공합니다.

자바스크립트에서 클로저를 만드는 가장 흔한 방법 중 하나는 함수 안에 또 다른 함수를 정의하는 것입니다. 이를 통해 내부 함수는 외부 함수의 변수에 접근할 수 있습니다.

아래는 클로저의 축약 표현을 보여주는 간단한 예제입니다:

javascriptCopy code
function outerFunction(outerVariable) { return function innerFunction() { console.log(outerVariable); }; } // 클로저를 변수에 할당 var closureExample = outerFunction("I am a closure"); // 클로저 호출 closureExample(); // "I am a closure"를 출력

이 예제에서 outerFunction은 내부 함수 innerFunction을 반환하며, innerFunction은 외부 함수의 outerVariable에 접근할 수 있습니다. closureExample은 outerFunction을 호출하여 반환된 클로저를 할당합니다. 이후 closureExample을 호출하면 "I am a closure"가 출력됩니다.

 

클로저의 축약 표현 정리

첫번째로 할수 있는것은 리턴형을 생략할 수 있다

두번째는 매개변수 생략하고 단축인자 사용

마지막으로 리턴형도 생략할 수 있다

 

 

클래스(Class)

 

객체 지향 프로그래밍(OOP)에서 "클래스(Class)"는 객체를 생성하기 위한 템플릿이며, 객체의 특성을 정의하는 데 사용됩니다. 클래스는 객체가 가져야 할 속성과 메서드를 정의합니다.

"인스턴스(Instance)"는 클래스의 실제 예시로, 클래스의 인스턴스는 클래스에 정의된 특성과 동작을 가지게 됩니다. 간단히 말해서, 클래스를 기반으로 생성된 객체를 인스턴스라고 합니다.

"객체(Object)"는 더 일반적인 용어로, 클래스의 인스턴스일 수도 있고, 변수, 데이터 구조 또는 함수 등의 모든 것을 지칭할 수 있습니다.

예를 들어, "사람"이라는 클래스가 있다고 가정해 봅시다. 그러면 "John"과 "Alice"라는 두 개의 객체가 "사람" 클래스의 인스턴스가 될 수 있습니다. 이때 "John"과 "Alice"는 "사람" 클래스의 특성과 동작을 공유하며, 각각의 개별적인 특성을 가지게 됩니다

 

 

Swift 에서 객체지향 용어를 property , Method 라고 불린다

 

클래스에서 프로퍼티를 추가 

- Property  는 초기값이 있어야한다

- init 을 이용하여 초기화

- optional 로 선

class Man {
var age: Int
var weight: Double

 

}

 

오류 : 생성자가 없어서 오류가난다,  age 값에 초기값이 없어서 오류,  weight 값에 초기값이 없어서 오류간다 

main.swift:1:7: error: class 'Man' has no initializers
class Man {
      ^
main.swift:2:9: note: stored property 'age' without initial value prevents synthesized initializers
    var age: Int
        ^
                 = 0
main.swift:3:9: note: stored property 'weight' without initial value prevents synthesized initializers
    var weight: Double
        ^
                       = 0.0

 

클래스를 optional 형으로 전환

class Man {
    var age: Int? = nil
    var weight: Double! = nil
}

 

눈에 안보이는 ( Default Initializer) 

클래스를 정의할 때 명시적으로 생성자를 작성하지 않아도, 컴파일러 또는 인터프리터가 기본 생성자(default constructor)를 제공하는 프로그래밍 언어들이 있습니다. 이런 언어들 중 일부는 다음과 같습니다:

  1. Java: 클래스에 생성자가 하나도 없을 경우, Java 컴파일러는 아무런 매개변수가 없고 아무런 동작도 하지 않는 기본 생성자를 자동으로 추가합니다.
java
public class MyClass {
    // 여기에는 별도의 생성자가 정의되어 있지 않습니다.
}
MyClass myObject = new MyClass(); // 이렇게 객체를 만들 수 있습니다.
  1. C#: C#에서도 클래스에 명시적인 생성자가 없으면, 컴파일러는 기본 생성자를 자동으로 추가합니다.
csharp
public class MyClass {
    // 여기에는 별도의 생성자가 정의되어 있지 않습니다.
}
MyClass myObject = new MyClass(); // 이렇게 객체를 만들 수 있습니다.
  1. Python: Python에서 클래스에 __init__ 메서드(생성자로 취급됨)가 없으면, 기본적으로 아무런 동작을 하지 않는 __init__ 메서드가 자동으로 제공됩니다.
python
class MyClass:
    # 여기에는 별도의 __init__ 메서드가 정의되어 있지 않습니다.

my_object = MyClass()  # 이렇게 객체를 만들 수 있습니다.
  1. Swift: Swift에서 구조체(struct)은 멤버 와이즈 초기화 구문(memberwise initializer)을 자동으로 제공합니다. 그러나 클래스(class)에서는 기본 초기화 구문을 제공하지 않으므로 명시적인 초기화 구문이 필요합니다.
  2. JavaScript (ES6+): JavaScript ES6부터 도입된 클래스 문법에서 constructor 함수가 생략되면 빈 함수로 처리됩니다.

위와 같은 언어들은 개발 편의성과 코드 가독성을 위해 묵시적인 혹은 디폴트 생성자 기능을 제공하고 있습니다.

 

 

인스턴스(객체) 를 만들고 메서드와 프로퍼티(속성)을 접근 

class Man{
var age : Int = 2
var weight : Double = 35.3
func display(){ //인스턴스 메서드
print("나이=\(age), 몸무게=\(weight)")
}
}
var x = 10
var SU : Man = Man() //새로 만든 SU 인스턴스 , 초기값을 주고 난 후 자료형 생략 가능
//눈에 안보이는 Default Initializer ,
print(SU.age)
SU.display();
 
class Man{
var age : Int = 1
var weight : Double = 3.5
init(age: Int, weight : Double){ //init 는 func 키워드를 사용안함
self.age = age //해당 클래스의 메서드나 프로퍼티의 접근 의미
self.weight = weight //매개변수의 이름과 프로퍼티의 이름이 같을 때는 self.을 써준다
} //designated initializer
init(age: Int){
self.age = age //overlodaing : 같은 이름의 함수를 여러번 쓰는 것
//overriding :
}
func display(){
print("나이=\(age), 몸무게=\(weight)")
}
}
var SU : Man = Man(age:10, weight:20.5)
SU.display()
var SU1: Man = Man(age:20)
SU1.display()

 

728x90
반응형
LIST