오늘은 Swift를 배우는데 있어서 가장 중요한 개념들이자 면접 단골 문제들에 대하여 살펴보록 하겠다. 아마 내가 작성한 "Swift 문법 심화, Ios 개발자 면접 직전 Swift 문법 중요 포인트 정리 시리즈" 중 가장 개념 정리가 머리속에 확실하게 되어야 하는 시리즈가 될 거 같다.
오늘 배울 개념들의 키워드이다
computed property, method overloading, method overriding, 상속, extension, access modifier, protocol
하나씩 개념을 혼내주도록 하자 다만 이전 시리즈 클레스 부분을 한번 읽고 오기 바란다.
https://aloe-study.tistory.com/163
오늘 개념들을 잘 이해한다면 면접시 면접관의 얼굴은 아래와 같을 것이다.
computed property
이전시간에에 클레스의 프로퍼티는 두가지가 있다고 했음 stored property 와 computed property 오늘은
computed property 대하여 알아보겠음
- 값을 리턴하는 게터(getter) 메서드
- 값을 대입하는 세터(setter) 메서드
즉 stored property 는 초기 값을 지정하거나 생성자를 통해 값을 가지고 있어야 하는 프로퍼티
computed property 는 따로 값을 리턴 하고 대입하는 게터와 세터를 통하여 값을 지정하는 프로퍼티
(미리 지정해서 사용 하는것이 아님)
computed property를 만드는 1단계 (특징 값을 변경하지 않더라도 var로 선언해야 함 )
class Man{
var age : Int = 1
var weight : Double = 3.5 // stored property 형태
var manAge : Int {
}
// computed property 만드는 1 단계 중괄호 묶어주기
func display(){
print("나이=\(age), 몸무게=\(weight)")
}
init(age: Int, weight : Double){
self.age = age //프로퍼티 = 매개변수
self.weight = weight
}
}
var kim : Man = Man(age:10, weight:20.5)
kim.display()
// 나이=10, 몸무게=20.5
computed property를 만드는 2단계
class Man{
var age : Int = 1
var weight : Double = 3.5
var manAge : Int {
get{
return age-1
}
}
// computed property 만드는 2 단계 getter 사용
// 따로 외부에서 사용하는게 아니라 어떻게 사용하겠다를 만들어주는
// 것임 return 필수로 해줘야함
func display(){
print("나이=\(age), 몸무게=\(weight)")
}
init(age: Int, weight : Double){
self.age = age //프로퍼티 = 매개변수
self.weight = weight
}
}
var kim : Man = Man(age:10, weight:20.5)
kim.display()
print(kim.manAge)
// 나이=10, 몸무게=20.5
// 9 // 넣어준적 없지만 잘 나옴
getter 생략
class Man{
var age : Int = 1
var weight : Double = 3.5
var manAge : Int {
// get{
return age-1
// }
}
//setter가 없으면 get{ }는 생략할 수 있으며 변경하지 않더라도 var로 선언해야 함
func display(){
print("나이=\(age), 몸무게=\(weight)")
}
init(age: Int, weight : Double){
self.age = age //프로퍼티 = 매개변수
self.weight = weight
}
}
var kim : Man = Man(age:10, weight:20.5)
kim.display()
print(kim.manAge)
// 나이=10, 몸무게=20.5
// 9 // 넣어준적 없지만 잘 나옴
getter와 setter를 갖는 computed property
class Man{
var age : Int = 1
var weight : Double = 3.5
var manAge : Int{
get{ // setter가 있기에 생략불가
return age-1
}
set(USAAge){
age = USAAge + 1
}
}
func display(){
print("나이=\(age), 몸무게=\(weight)")
}
init(age: Int, weight : Double){
self.age = age
self.weight = weight
}
}
var kim : Man = Man(age:10, weight:20.5)
kim.display()
print(kim.manAge) //9, getter호출
print(kim.age) //10
kim.manAge = 3 //setter호출
print(kim.age) //4
즉 셋터를 먼저 이용하지 않고 사용한다면 기본으로 getter 가 동작하고
setter를 이용하겠다 말해야 setter를 동작 시킴
Shorthand Setter Declaration
setter의 매개변수를 생략하면 Swift는 기본적으로 newValue 라는 이름으로 가지고 놀 수 있게 잡아줌
그래서 setter의 매개변수명이 newValue인 경우에만 이렇게 “(newValue)” 생략 가능
// set{
// age = newValue + 1
// }
class Man{
var age : Int = 1
var weight : Double = 3.5
var manAge : Int{
get{ return age-1 }
set{ age = newValue + 1 }
}
func display(){
print("나이=\(age), 몸무게=\(weight)")
}
init(age: Int, weight : Double){
self.age = age
self.weight = weight
}
}
var kim : Man = Man(age:10, weight:20.5)
kim.display()
print(kim.manAge) //9, getter호출
print(kim.age) //10
kim.manAge = 3 //setter호출
print(kim.age) //4
// 매개변수명은 newValue가 기본
// set(newValue){
// age = newValue + 1
// }
// Shorthand Setter Declaration
// setter의 매개변수명이 newValue인 경우에만 이렇게 “(newValue)” 생략 가능
// set{
// age = newValue + 1
// }
method overloading vs method overriding
메서드 오버로딩과 메서드 오버라이딩이 이것에 대한 차이가 무엇인지 정확히 알고 있는가?
면접시 이 질문이 나왔을때 속으로 어? 라는 생각이 아닌 자신감 넘치게 설명할 수 있는 모습을 상상하며 글을 읽어보자
미리 말 하자면
둘다 공통점은 메서드가 같은 이름으로 사용 될수 있다라는 것인데
오버로딩은 하나의 클레스 안에서 같은 이름 메소드간에 관계를 말하는 거고
오버라이딩은 자식과 부모간에 같은 이름 메소드간에 관계를 말하는 것임
method overloading : 생성자 중첩 및 일반 메서드 중첩 (주의사항 까지)
위에서 말한대로 지금 같은 클레스 안에서 같은 이름 메서드가 2개임
이게바로 method overloading 같은 이름의 메소드를 중복하여 정의하는 것을 의미함
단 완전 같으면 오류가 나고 매개변수의 개수와 자료형이 달라야 오류 안남
어떻게 보면 순수 이름만 같다고 볼수 있음 동명이인 개념
class Man{
var age : Int = 1
var weight : Double = 3.5
func display(){
print("나이=\(age), 몸무게=\(weight)")
}
func display(age:Int){
print("나이=\(age), 몸무게=\(weight)")
}
// 매개변수의 개수와 자료형이 달라야 오류 안남
// func display(){
// print("나이=\(age), 몸무게=\(weight)")
// }
init(age: Int, weight : Double){ //1
self.age = age
self.weight = weight
}
init(age: Int){ //2
self.age = age
}
}
var kim : Man = Man(age:10, weight:20.5) //1
var kim1 : Man = Man(age:10) //2
//var kim2 : Man = Man()
//init가 없다면 인스턴스 만드는 방법
kim.display()
kim1.display()
kim1.display(age:3)
// 나이=10, 몸무게=20.5
// 나이=10, 몸무게=3.5
// 나이=3, 몸무게=3.5
아니 그렇다면 왜? 사용하는데? 아래 공식 문서를 들어가보자 아래는 다음 시간에 이야기 하겠지만 Swift로 앱 개발을 하는데 있어서 필요한 클레스인데 같은이름의 생성자가 엄청 중복 즉 method overloading 되어있다.
이렇게 사용하는 이유는 개발자들이 자신이 만든 클레스가 아니기 때문에 어려움을 느낄 수 있어
객체지향언어의 가장 큰 목적인 재사용에 부합하기 위해 즉 여러 개발자가 내가 만든 클레스가 아닌데도 불구하고 인스턴스를 생성하기 편하게 위함이다.
ex 이름 하나만 알고 있으면 다양하게 입력 매개변수 등 만 바꿔서 사용하면 되니까
https://developer.apple.com/documentation/uikit/uiimage
method overriding
앞서 배운 오버로딩(overloading)은 서로 다른 기능을 갖는 여러 메소드를 하나의 이름으로 정의하는 것이었습니다.
오버라이딩(overriding)이란 상속 관계에 있는 부모 클래스에서 이미 정의된 메소드를 자식 클래스에서 같은 시그니쳐를 갖는 메소드로 다시 정의하는 것이라고 할 수 있습니다.
그렇기 때문에 우리는 상속이라는 것을 알아야함
inheritance 상속
- 상속된 클래스는 부모 클래스의 모든 기능을 상속받으며, 자신만의 기능을 추가
- 상속받은 클래스들을 하위 클래스(subclass) 또는 자식 클래스(child class)
- 하위 클래스가 상속받은 클래스는 부모 클래스(parent class) 또는 상위 클래스(super class)
- 단일 상속 (single inheritance)
Swift에서 하위 클래스는 단 하나의 부모 클래스만 상속받을 수 있음
C++을 제외한 대부분 언어 단일 상속임 그렇기 때문에 부모는 하나만 올 수 있음
용어정리
부모 클레스를 자식 클레스가 상속받았다고 함
조금 이따 배울 프로토콜은 자바의 인터페이스와 비슷한 개념이며
여러 개를 채택할 수 있음 프로토콜은 상속이 아니라 채택한다고 함
구조
class Man{
var age : Int = 1
var weight : Double = 3.5
func display(){
print("나이=\(age), 몸무게=\(weight)")
}
init(age: Int, weight : Double){
self.age = age
self.weight = weight
}
}
class Student : Man {
//비어있지만 Man의 모든 것을 가지고 있음
}
//var kim : Man = Man.init(age:10, weight:20.5) 생성자도 함수라 이렇게 사용할수 있음 여담
var kim : Man = Man(age:10, weight:20.5)
kim.display()
var lee : Student = Student(age:20,weight:65.2)
lee.display()
print(lee.age)
// 나이=10, 몸무게=20.5
// 나이=20, 몸무게=65.2
// 20
// 상속된 클래스는 부모 클래스의 모든 기능을 상속받으며, 자신만의 기능을 추가
super : 부모 메서드 호출 시 사용
class Man{
var age : Int
var weight : Double
func display(){
print("나이=\(age), 몸무게=\(weight)")
}
init(age: Int, weight : Double){
self.age = age
self.weight = weight
}
}
class Student : Man {
var name : String
func displayS() {
print("이름=\(name), 나이=\(age), 몸무게=\(weight)")
}
init(age: Int, weight : Double, name : String){
self.name = name
super.init(age:age, weight:weight) //과제: 이 줄을 안쓰면?
}//error:'super.init' isn't called on all paths before returning from initializer
}
// 부모에 프러퍼티에 초기 값이 없어서 이렇게 안해주면 오류가 남 그렇기 때문에 이렇게
// super 키워드로 부모 생성자에 접근
var lee : Student = Student(age:20,weight:65.2,name:"홍길동")
lee.displayS()
lee.display()
// 이름=홍길동, 나이=20, 몸무게=65.2
// 나이=20, 몸무게=65.2
// init(age1: Int, weight1 : Double, name : String){
// super.init(age:age1, weight:weight1)
// self.name = name
// }
// }
// var lee : Student = Student(age1:20,weight1:65.2,name:"홍길동")
// 즉 넘어오는걸 부모 쪽으로 바로 주는 것임 이해를 돕기 위한 소스
// 어짜피 부모의 모든걸 사용가능하니까 상속하면 lee.displayS() 했을때 결과는 이러함
이제 진짜 override를 알아보자
method overriding : 내가 만든 걸 최우선 적용해 줘라
사실 크게 어려운 개념은 아니다 상속을 배웠기 때문에 이해가 빠를 것이다.
class Man{
var age : Int = 1
var weight : Double = 3.5
func display(){
print("나이=\(age), 몸무게=\(weight)")
}
init(age: Int, weight : Double){
self.age = age
self.weight = weight
}
}
class Student : Man {
var name : String = "김소프"
override func display() {
print("이름=\(name), 나이=\(age), 몸무게=\(weight)")
}
init(age: Int, weight : Double, name : String){
super.init(age:age, weight:weight)
self.name = name
}
}
var lee : Student = Student(age:20,weight:65.2,name:"홍길동")
lee.display()
// 이름=홍길동, 나이=20, 몸무게=65.2
• 부모와 자식에 display()라는 메서드가 있어서 Student클래스는 display() 메서드가 두 개임
• Student클래스의 인스턴스 lee가 display()를 호출할 때, 자식클래스가 새로 만든 display() 메서드가 우선적으로 호출되려면 func 앞에 override키워드 씀
• 내가 만든걸 최우선 적용 해줘라 : override
extension : class, struct, enum, protocol에 새로운 기능을 추가
확장? 이게 무엇일까?
사실 이것도 크게 어려울것 없다. 항상 존재하는지도 모르고 있는게 문제일 뿐이다.
- extension은 하위 클래스를 생성하거나 참조하지 않고 기존 클래스에 메서드, 생성자(initializer), 계산 프로퍼티 등의 기능을 추가하기 위하여 사용
- Swift의 built-in클래스와 iOS 프레임워크에 내장된 클래스에 기능을 추가할 때, extension을 이용하면 매우 효과적임
- 클래스(구조체, 열거형, protocol)는 다음과 같은 형태로 확장(익스텐션)함
extension 기존타입이름 {
// 새로운 기능
}
https://developer.apple.com/documentation/swift/double
자 우리가 자주 사용하는 더블형은 구조체로 만들어져 있다.
공식 문서를 보면 다양한 기능들을 할 수 있는것으로 보여진다. 근데 더블형의 기능중 제곱을 하는 기능은 보이지 않는다 그래서
새로운 기능을 추가해보려고 할때 사용하는게 extension 이다.
(기존 기능을 건드는 게 아님 좀더 우리가 필요한 기능을 입맛에 따라 추가하는 것임)
extension Double {
var squared : Double { //기존 Double형 구조체에 계산 프로퍼티 추가
return self * self
}
var up : Double { //기존 Double형 구조체에 계산 프로퍼티 추가
return self + 1.0
}
}
let myValue: Double = 3.0
print(myValue.squared)
print(2.0.squared) //Double형 값에도 .으로 바로 사용 가능
let myValue2: Double = 3.0
print(myValue2.up)
print(2.0.up) //Double형 값에도 .으로 바로 사용 가능
// 9.0
// 4.0
// 4.0
// 3.0
access modifier(or access specifiers) : 접근 속성
- 접근 속성(접근 수정자, 액세스 수정자, 액세스 지정자 )는 클래스, 메서드, 멤버의 접근 가능성을 설정하는 객체 지향 언어의 키워드
- 구성 요소를 캡슐화 하는 데 사용
- 노란 색은 언어별 디폴트 접근 속성
https://en.wikipedia.org/wiki/Access_modifiers
Swift는 형광펜 친 5 가지가 디폴트 접근 속성임
public class MyClass{
// 모듈의 모든 소스 파일 내에서 접근+정의한 모듈을 가져오는 다른 모듈의 소스파일에서도 접근 가능
fileprivate var name : String = "Kim"
//현재 소스 파일 내에서만 사용 가능
private func play() {}
//현재 블럭 내에서만 사용 가능
func display(){} //internal은 디폴트 속성으로 생략됨
//해당 모듈의 모든 소스 파일 내에서 사용
}
모듈은 코드 배포(code distribution)의 단일 유닛
1. 앱, Framework(UIKit 등),외부라이브러리
2. import Alamofire
open 접근 및 public 접근을 통해 모듈의 모든 소스 파일 내에서 사용할 수 있으며, 정의한 모듈을 가져오는 다른 모듈의 소스파일에서도 사용할 수 있다. 일반적으로 Framework에 공용 인터페이스를 지정할 때는 open 또는 public 접근을 사용한다.
- open 접근은 클래스 및 클래스 멤버에만 적용
internal 접근은 해당 모듈의 모든 소스 파일 내에서 사용되지만, 해당 모듈 외부의 소스파일에서는 사용되지 않도록 한다. 일반적으로 App이나 Framework의 내부 구조를 정의할 때 internal 접근을 사용한다.
- 접근 제어를 생략하면 internal이 기본
fileprivate 접근은 해당 소스 파일 내에서만 사용가능
private접근은 블록과 동일한 파일에 있는 해당 선언의 extension으로 제한한다.
이전 시간에 알아본 메서드 내용에서
https://aloe-study.tistory.com/163
클레스, 타입 메서드도 여기에 포함되어 있는 개념이라 추가적으로 설명 하기 위해서 이번 챕터로 뺏다.
상속 + 접근 속성 개념을 알아야 하기에
class SClass {
var storedProperty = 2
static var storedTypeProperty = 1
static var computedTypeProperty: Int {
return 10
}
class var overrideableComputedTypeProperty: Int {
return 100
}
}
var x = SClass()
print(x.storedProperty) // 인스턴스가 가지고 놈
print(SClass.storedTypeProperty)
print(SClass.computedTypeProperty)
print(SClass.overrideableComputedTypeProperty)
// 2
// 1
// 10
// 100
// static, class 붙은 애들은 클레스가 가지고 노는 것임
Class 붙은 애들은 상속이 가능함!!!!!!
프로토콜(protocol)
즉 구현 된 것은 아무 것도 없는 밑 그림만 있는 기본 설계도 이다.
자바, C#의 interface : 미리 정의해준다고 생각 이러이러한 거 필요하니까 잊지 말고 사용해라
다시한번 클레스 상속과 프로토콜 채택 구조에 대하여 살펴보자
protocol 정의
protocol 프로토콜명{
프로퍼티명
메서드 선언 //메서드는 선언만 있음
}
protocol 프로토콜명 : 부모1프로토콜, 부모2프로토콜{
// 프로토콜은 다중 상속 즉 다중 채택도 가능
}
protocol Runnable { //대리하고 싶은 함수 목록 작성
var x : Int {get set} //읽기와 쓰기 가능 프로퍼티,{get}은 읽기 전용
//property in protocol must have explicit { get } or { get set } specifier
func run() //메서드는 선언만 있음
}
class Man : Runnable { //채택, adopt
var x : Int = 1 //준수, conform
func run(){print("달린다~")} //준수, conform
}
let woogie = Man()
woogie.run()
// class Man에 x, run()정의 없다면
// type 'Man' does not conform to protocol 'Runnable‘
// 즉 준수 해줘야함 프로퍼티에는 값을 넣어줘야 하고 메서드에는 기능을 넣어야함
// 달린다~
프로토콜 및 클레스 상속 문제 풀어보기
다음과 같은 기능을 전체 하나의 소스로 작성하시오.
// bb()라는 메소드가 하나있는 프로토콜(protocol) B을 만드시오.
// bb()메서드는 Int형 값을 매개변수로 받아 Int형으로 리턴하는 메서드이다.
// 클래스 A는 클래스 C라는 부모를 갖는다(C로부터 상속받는다).
// 클래스 A에서 프로토콜 B를 채택하고, 준수하는 소스를 작성하시오.
// bb()메서드는 Int형 값을 매개변수로 받아 두 배한 값을 Int형으로 리턴하는 메서드이다.
// 클래스 A의 인스턴스 a를 만들고 bb를 호출(argument로 3을 입력)하여 결과를 확인하세요
정답
protocol B {
func bb(x: Int) -> Int
}
class C { //채택, adopt
}
class A : C, B {
func bb(x : Int) -> Int{
return x * 2
}
}
var a : A = A()
print(a.bb(x:3))
// 6
다시 복습 : 용어정리
부모 클레스를 자식 클레스가 상속받았다고 함
조금 이따 배울 프로토콜은 자바의 인터페이스와 비슷한 개념이며
여러 개를 채택할 수 있음 프로토콜은 상속이 아니라 채택한다고 함
나의 Swift 문법 중요 포인트 정리 시리즈를 여기 까지 정독했다면 Swift의 문법은 90% 정도 파악 한것이다.
자부심과 자신감을 나와 같이 가지길 바라며 모든 취준생 및 주니어 개발자들이 도움이 되었으면 한다. 혹여나
시니어급 개발자 분들이 이 글을 본다면 민망하지만 여기까지 읽어주셔서 감사합니다.
이 시리즈의 자료출처는
대한민국에서 가장 Swift, Ios 프로그래밍에 대하여 지식이 많으신
유튜버 스마일 한 님 (제가 가장 존경하는 교수님 중 한 분이십니다.) 자료를 참고하였습니다.
https://www.youtube.com/channel/UCM8wseo6DkA-D7yGlCrcrwA
+
추가 자료
http://www.tcpschool.com/java/java_inheritance_overriding
'APP > Swift' 카테고리의 다른 글
애플 공식 디자인 가이드 라인 사이트 (0) | 2022.11.03 |
---|---|
Swift 문법 심화, Ios 개발자 면접 직전 Swift 문법 중요 포인트 정리3 1급 객체, 1급 시민, 클로저, 클래스, (0) | 2022.10.02 |
Swift 문법 심화, Ios 개발자 면접 직전 Swift 문법 중요 포인트 정리2 Any, 연산자, 조건문, 반복문 , Call by reference (0) | 2022.10.01 |
Swift 문법 심화, Ios 개발자 면접 직전 Swift 문법 중요 포인트 정리1 자료형 (숫자형, 문자형, 옵셔널, 변수 상수 선언) (0) | 2022.10.01 |
iOS 개발자라면 꼭 봐야 할 Swift 관련 문서 (1) | 2022.09.20 |