신속한 언어 구조와 클래스


192

Apple의 책에서 "구조와 클래스의 가장 중요한 차이점 중 하나는 코드에서 구조가 전달 될 때 구조가 항상 복사되지만 클래스는 참조로 전달된다는 것입니다."

누구든지 그것이 무엇을 의미하는지 이해하도록 도울 수 있습니까? 나에게 수업과 구조체는 같은 것 같습니다.


3
.NET에서 구조체와 클래스의 차이점을 참조하십시오 : stackoverflow.com/a/13275/19100 , Swift가 동일한 의미를 사용한다고 생각합니다.
dalle

23
@ jonrsharpe는 당신에게 쉬울 수 있습니까? 이걸
아시면

1
가치 대 참조는 OOP만의 개념이 아닙니다. void my_func(int a)vs 와 같은 C에 void my_func(int &a)있습니다. 이것은 프로그래밍의 매우 근본적인 질문입니다. 더 읽어보기 : stackoverflow.com/questions/373419/…
superarts.org

답변:


473

다음은의 예입니다 class. 이름이 변경되면 두 변수가 참조하는 인스턴스가 어떻게 업데이트되는지 확인하십시오. 참조 된 모든 곳에서 Bob이제 입니다.SueBob

class SomeClass {
    var name: String
    init(name: String) {
        self.name = name
    }
}

var aClass = SomeClass(name: "Bob")
var bClass = aClass // aClass and bClass now reference the same instance!
bClass.name = "Sue"

println(aClass.name) // "Sue"
println(bClass.name) // "Sue"

이제는 struct값이 복사되고 각 변수가 자체 값 세트를 유지한다는 것을 알 수 있습니다. 우리가 이름을 설정할 때 SueBob에서 구조체는 aStruct변경되지 않습니다.

struct SomeStruct {
    var name: String
    init(name: String) {
        self.name = name
    }
}

var aStruct = SomeStruct(name: "Bob")
var bStruct = aStruct // aStruct and bStruct are two structs with the same value!
bStruct.name = "Sue"

println(aStruct.name) // "Bob"
println(bStruct.name) // "Sue"

따라서 상태 저장 복합 엔티티를 나타내는 class것은 굉장합니다. 그러나 단순히 관련 데이터의 측정 또는 비트 인 struct값의 경우 부작용을 두려워하지 않고 쉽게 복사하고 계산하거나 값을 수정할 수 있도록 더 의미가 있습니다.


"하지만없는 값 에는 단순히 숫자보다 더 복잡 ..."이 알렉스 주셔서 감사합니다
마이크 Rapadas

7
@MichaelRapadas 번호는 실제로 있습니다 스위프트의 구조체.
Nikolai Ruhe

aStruct and bStruct are two structs with the same value!구조체 내부의 변수 값이 다르기 때문에 이것을 혼란스럽게 할 수 있습니까 ?
Julian Król

@ JulianKról 그 라인 aStructbStruct동일한 값을 갖는다. 둘 다 단일 name필드로 설정되어 "Bob"있습니다. 그러나 그들은 두 개의 다른 구조체입니다. 이것은 구조체 중 하나의 이름을 변경할 수 있고 다른 하나는 변경되지 않은 경우 다음 줄에서 입증됩니다.
Alex Wayne

과제를 놓쳤습니다. 감사합니다. 어쩌면 그것은 너무 더워 :-)
Julian Król

60

클래스와 구조는 모두 다음을 수행 할 수 있습니다.

  • 값을 저장할 속성 정의
  • 기능을 제공하는 방법 정의
  • 확장
  • 프로토콜 준수
  • 인티 사이 저 정의
  • 변수에 액세스 할 수 있도록 첨자를 정의

수업 만 할 수 있습니다 :

  • 계승
  • 타입 캐스팅
  • deinitialisers 정의
  • 여러 참조에 대한 참조 횟수를 허용합니다.

32

struct가치 유형입니다. 이는 구조의 인스턴스를 다른 변수에 복사하면 변수에 복사 된 것입니다.

값 유형의 예

struct Resolution {
    var width = 2
    var height = 3
}

let hd = Resolution(width: 1920, height: 1080)
var cinema = hd //assigning struct instance  to variable
println("Width of cinema instance is \(cinema.width)")//result is 1920
println("Width of hd instance is \(hd.width)")//result is 1920

cinema.width = 2048

println("Width of cinema instance is \(cinema.width)")//result is 2048
println("Width of hd instance is \(hd.width)")//result is 1920

클래스는 참조 유형입니다. 그것은 당신이 변수에 클래스의 인스턴스를 할당하면, 그것은 단지 유지된다는 것을 의미합니다 참조 인스턴스와에 없는 복사본을 .


5
"클래스의 인스턴스를 다른 변수에 지정하면 복사되지 않은 인스턴스의 참조 만 보유합니다."
Saif

8

위의 답변이 정확합니다. 내 답변이 위의 답변을 이해하지 못하는 사람에게 도움이되기를 바랍니다.

Swift에는 두 가지 유형의 객체가 있습니다.

  1. 구조
  2. 수업

그들 사이의 주요 차이점은

  • 구조는 가치 유형
  • 클래스는 참조 유형입니다

예를 들어 여기에 코드가 잘 이해되어 있습니다.

struct SomeStruct {
var a : Int;

init(_ a : Int) {
    self.a = a
}
}

class SomeClass {
var a: Int;

init(_ a: Int) {
    self.a = a
}

}
var x = 11

var someStruct1 = SomeStruct(x)
var someClass1 = SomeClass(x)

var someStruct2 = someStruct1
var someClass2 = someClass1

someClass1.a = 12
someClass2.a // answer is 12 because it is referencing to class 1     property a

someStruct1.a = 14
someStruct2.a // answer is 11 because it is just copying it not referencing it

이것이 주요한 차이점이지만 하위 차이점도 있습니다.

수업

  1. 이니셜 라이저를 선언해야합니다 (생성자).
  2. deinitialisers가 있습니다
  3. 다른 클래스에서 상속 가능

구조

  1. 그것은 당신을 위해 무료 이니셜 라이저를 가지고 있습니다. 무료 이니셜 라이저를 선언하면 이니셜 라이저를 선언 할 필요가 없습니다. 선언 된 이니셜 라이저가 덮어 씁니다.
  2. deinitialiser가 없다
  3. 다른 구조체에서 상속 할 수 없습니다

7

이 질문은 중복 된 것으로 보이지만 다음은 대부분의 사용 사례에 대한 답변입니다.

  1. 구조체와 클래스의 가장 중요한 차이점 중 하나는 구조체가 값 형식이며 코드에서 전달 될 때 항상 복사되며 클래스는 참조 형식이며 참조로 전달된다는 것입니다.

  2. 또한 클래스에는 상속이있어 한 클래스가 다른 클래스의 특성을 상속 할 수 있습니다.

  3. 구조 속성은 스택에 저장되고 클래스 인스턴스는 힙에 저장되므로 때때로 스택이 클래스보다 훨씬 빠릅니다.

  4. Struct는 기본 초기화 프로그램을 자동으로 가져 오는 반면 Class에서는 초기화해야합니다.

  5. Struct는 언제든지 스레드 안전 또는 싱글 톤입니다.

또한 구조체와 클래스의 차이점을 요약하려면 값과 참조 유형의 차이점을 이해해야합니다.

  1. 값 유형의 사본을 작성하면 복사중인 항목의 모든 데이터가 새 변수에 복사됩니다. 그것들은 2 개의 분리 된 것들이며 하나를 바꾸는 것은 다른 것에 영향을 미치지 않습니다.
  2. 참조 유형의 사본을 작성할 때 새 변수는 복사중인 것과 동일한 메모리 위치를 나타냅니다. 즉, 둘 다 동일한 메모리 위치를 참조하기 때문에 하나를 변경하면 다른 하나도 변경됩니다. 아래 샘플 코드는 참조로 사용할 수 있습니다.

// sampleplayground.playground

  class MyClass {
        var myName: String
        init(myName: String){
            self.myName = myName;
        }
    }

    var myClassExistingName = MyClass(myName: "DILIP")
    var myClassNewName = myClassExistingName
    myClassNewName.myName = "John"


    print("Current Name: ",myClassExistingName.myName)
    print("Modified Name", myClassNewName.myName)

    print("*************************")

    struct myStruct {
        var programmeType: String
        init(programmeType: String){
            self.programmeType = programmeType
        }
    }

    var myStructExistingValue = myStruct(programmeType: "Animation")
    var myStructNewValue = myStructExistingValue
    myStructNewValue.programmeType = "Thriller"

    print("myStructExistingValue: ", myStructExistingValue.programmeType)
    print("myStructNewValue: ", myStructNewValue.programmeType)

산출:

Current Name:  John
Modified Name John
*************************
myStructExistingValue:  Animation
myStructNewValue:  Thriller

안녕하세요 Dilip, "언제나 시간에 구조는 스레드 안전 또는 싱글 톤"에 대한 예를 제공 할 수 있습니까?. 미리 감사드립니다.
Narasimha Nallamsetty

3

애플 핸드북에서 더 먼 곳을 살펴보면 "구조와 열거가 가치 유형입니다"라는 섹션이 보일 것입니다.

이 섹션에는 다음이 표시됩니다.

“hd = 해상도 (너비 : 1920, 높이 : 1080) var 시네마 = hd이 예에서는 hd라는 상수를 선언하고이를 해상도로 설정합니다. 풀 HD 비디오의 너비와 높이로 초기화 된 인스턴스 (가로 1920 x 1080 픽셀).

그런 다음 영화라는 변수를 선언하고 hd의 현재 값으로 설정합니다. Resolution은 구조이므로 기존 인스턴스의 사본이 만들어지고이 새로운 사본이 영화관에 할당됩니다. hd와 영화는 이제 너비와 높이가 동일하지만 장면 뒤에서 완전히 다른 두 인스턴스입니다.

다음으로 시네마의 너비 속성이 디지털 시네마 프로젝션에 사용되는 약간 더 넓은 2K 표준의 너비 (2048 픽셀 및 1080 픽셀 높이)로 수정되었습니다.

영화관 = 너비 = 2048 영화의 너비 속성을 확인하면 실제로 2048로 변경되었음을 알 수 있습니다.

println ( "시네마는 이제 (시네마 폭) 픽셀 폭") // 인쇄 "시네마는 이제 2048 픽셀 폭이지만 원래 hd 인스턴스의 너비 속성은 여전히 ​​오래된 1920의 가치 :

println ( "hd는 여전히 (폭) 픽셀 너비") // // "hd는 여전히 1920 픽셀입니다"

영화에 hd의 현재 값이 주어지면 hd에 저장된 값이 새 영화 인스턴스에 복사되었습니다. 최종 결과는 완전히 동일한 두 개의 인스턴스이며 동일한 숫자 값을 포함했습니다. 별도의 인스턴스이기 때문에 영화의 너비를 2048로 설정해도 HD에 저장된 너비에는 영향을 미치지 않습니다.”

발췌 : Apple Inc.“Swift Programming Language.” iBooks. https://itun.es/us/jEUH0.l

이것은 구조체와 클래스의 가장 큰 차이점입니다. 구조체가 복사되고 클래스가 참조됩니다.


1

일반적으로 (대부분의 프로그래밍 언어에서) 객체는 힙에 저장된 데이터 블록이며 이러한 블록에 대한 참조 (일반적으로 포인터)에는 name이러한 데이터 블록에 액세스 하는 데 사용됩니다. 이 메커니즘을 사용하면 참조 (포인터)의 값을 복사하여 힙의 객체를 공유 할 수 있습니다. 이것은 정수와 같은 기본 데이터 유형의 경우가 아니며, 참조를 작성하는 데 필요한 메모리가 오브젝트 (이 경우 정수 값)와 거의 동일하기 때문입니다. 따라서 큰 객체의 경우 참조가 아닌 값으로 전달됩니다.

Swift는 struct를 사용하여 String 및 Array 객체에서도 성능을 향상시킵니다.

정말 좋은 독서


1

Structs와 클래스의 차이점을 이해하려면 값과 참조 유형의 주요 차이점을 알아야합니다. 구조는 값 유형이며, 그에 대한 모든 변경은 해당 값만 수정하고, 클래스는 참조 유형이며, 참조 유형의 모든 변경은 해당 메모리 또는 참조 위치에 할당 된 값을 수정합니다. 예를 들면 다음과 같습니다.

클래스로 시작하겠습니다.이 클래스는 인스턴스를 비교할 수 있도록 Equatable을 준수합니다. 인스턴스를 만들고 pointClassInstanceA다른 pointClassInstanceB클래스를 클래스 B에 할당합니다. 이제 주장은 동일합니다 ...

class PointClass: Equatable {
    var x: Double
    var y: Double

    init(x: Double, y: Double) {
        self.x = x
        self.y = y
    }

    static func == (lhs: PointClass, rhs: PointClass) -> Bool {
        return lhs.x == rhs.x && lhs.y == rhs.y
    }
}

var pointClassInstanceA = PointClass(x: 0, y: 0)
var pointClassInstanceB = pointClassInstanceA

assert(pointClassInstanceA==pointClassInstanceB) 

pointClassInstanceB.x = 10
print(pointClassInstanceA.x)
//this prints 10

자, pointsClassInstanceB의 x 값을 변경하면 pointClassInstanceA의 x 값도 변경된 이유는 무엇입니까? 글쎄, 이것은 인스턴스 A를 인스턴스 B의 값으로 할당 할 때 참조 유형이 작동하는 방식을 보여줍니다. 그중 하나의 X를 수정하면 동일한 참조를 공유하기 때문에 X의 두 가지가 변경되고 그 값이 변경된 것은 무엇입니까? 참고.

똑같이하지만 구조체로하자

struct PointStruct: Equatable {
    var x: Double
    var y: Double

    init(x: Double, y: Double) {
        self.x = x
        self.y = y
    }

    static func == (lhs: PointStruct, rhs: PointStruct) -> Bool {
        return lhs.x == rhs.x && lhs.y == rhs.y
    }
}
var pointStructInstanceA = PointStruct(x: 0, y: 0)
var pointStructInstanceB = pointStructInstanceA

assert(pointStructInstanceA==pointStructInstanceB)
pointStructInstanceB.x = 100
print(pointStructInstanceA.x)
//this will print 0

우리는 기본적으로 클래스와 동일한 구조를 가지지 만 이제 pointStructInstanceA의 x 값을 인쇄 할 때이 값이 변경되지 않았으며 값 유형이 다르게 작동하고 인스턴스 중 하나에 대한 모든 변경이 " 독립적 인 "및 다른 영향을 미치지 않습니다.

Swift는 더 많은 값 유형을 사용하도록 제안하며 라이브러리가 의도하지 않은 값 수정 등과 같은 참조 유형으로 인해 발생하는 문제를 피하기위한 구조체를 기반으로한다는 것을 알 수 있습니다. Structs는 Swift를 진행하는 방법입니다. 도움이 되길 바랍니다.


1

다음은 구조체와 클래스의 차이점을 정확하게 보여주는 예입니다.

놀이터에서 작성된 코드의 스크린 샷
놀이터에서 작성된 코드의 스크린 샷

struct Radio1{
    var name:String
    //    init(name:String) {
    //        self.name = name
    //    }
}

struct Car1{
    var radio:Radio1?
    var model:String

}

var i1 = Car1(radio: Radio1(name:"murphy"),model:"sedan")
var i2 = i1
//since car instance i1 is a struct and 
//this car has every member as struct ,
//all values are copied into i2

i2.radio?.name //murphy
i2.radio = Radio1(name: "alpha")
i2.radio?.name //alpha

i1.radio?.name //murphy

//since Radio1 was struct , 
//values were copied and thus
// changing name  of instance of Radio1 in i2 
//did not bring change in i1

class Radio2{
    var name:String
    init(name:String) {
        self.name = name
    }
}

struct Car2{
    var radio:Radio2?
    var model:String

}
var i3 = Car2(radio: Radio2(name:"murphy"),model:"sedan")
//var radioInstance = Radio2(name: "murphy")
//var i3 = Car2(radio: radioInstance,model:"sedan")

var i4 = i3
//since i3 is instance of struct
//everything is copied to i4 including reference of instance of Radio2
//because Radio2 is a class



i4.radio?.name //murphy
i4.radio?.name="alpha"
i4.radio?.name //alpha

i3.radio?.name //alpha

//since Radio2 was class, 
//reference was copied and 
//thus changing name of instance 
//of Radio2 in i4 did  bring change in i3 too


//i4.radio?.name
//i4.radio = Radio2(name: "alpha")
//i4.radio?.name
//
//i3.radio?.name

1
1.structure is value type.
   = > when we assign structure variable to other variable or pass as parameter to function, it creates separate/new copy => so that changes made on one variable does not  reflect on another.[We can say like **call by value** concept] 
Example :

    struct DemoStruct 
    { 
        var value: String 
        init(inValue: String) 
        { 
            self.value = inValue 
        } 
    } 


var aStruct = DemoStruct(inValue: "original") 
var bStruct = aStruct // aStruct and bStruct are two structs with the same value! but references to diff location`enter code here`
bStruct.value = "modified" 

print(aStruct.value) // "original" 
print(bStruct.value) // "modified"


2.class is reference type.
 = > when we assign structure variable to other variable or pass as parameter to function, it **does not** creates separate/new copy => so that changes made on one variable does not  reflect on another.[We can say like **call by reference** concept] 
Example:
class DemoClass 
{   
    var value: String 
    init(inValue: String) 
    {
        self.value = inValue 
    } 
} 

var aClass = DemoClass(inName: "original") 
var bClass = aClass // aClass and bClass now reference the same instance! 
bClass.value = "modified" 

print(aClass.value) // "modified" 
print(bClass.value) // "modified"

1

스위프트 타입

Value type 변수 또는 상수에 할당되거나 함수에 전달 될 때 값이 복사되는 유형입니다.

Reference types 변수 나 상수에 할당되거나 함수에 전달 될 때 복사되지 않습니다

값 종류 :
Struct, Enum, Tuple
struct String, struct Array( Set, Dictionary)

  • 언제 할당하거나 전달할 value type 새로운 사본 데이터가 생성된다. 실제로 copy on write- COW메커니즘은 일부 최적화와 함께 사용됩니다. 예를 들어 오브젝트가 수정 될 때 사본이 작성됩니다.
  • 인스턴스 를 수정 하면 로컬 효과 만 있습니다.
  • 스택 메모리가 사용됩니다.

참조 유형 :
Class,Function

  • 원본 인스턴스에 새 참조 를 할당하거나 전달 reference type하면 인스턴스의 주소가 복사됩니다.
  • 인스턴스 를 수정 하면 인스턴스 를 가리키는 모든 참조가 인스턴스를 공유하고 액세스 할 수 있기 때문에 전체 효과가 있습니다.
  • 힙 메모리가 사용됩니다.

여기에 이미지 설명을 입력하십시오

Value type기본적 으로 사용 하는 것이 좋습니다 . 가장 큰 장점은 Value type일반적으로thread safe

Reference type 장점 :

  • 그들은 상속받을 수 있고
  • deinit() 사용할 수 있습니다
  • 참조로 인스턴스를 비교 ===하고
  • Objective-CValue TypeSwift에 도입 되었기 때문에 상호 운용성

[Mutability에 대한 추가 정보]
구조와 클래스
유형 선택
클래스와 구조


0

이미 이것에 대해 많은 글이 있습니다. 비유를 추가하고 싶습니다. 이것 이후에 당신이 결코 염두에 두지 않기를 바랍니다 : 결론 : 클래스는 참조로 전달되는 반면 구조체는 값으로 전달됩니다.

친구와 Google 문서를 공유한다고 가정 해 보겠습니다. 이제 그가 그 내용을 변경하면 Google 문서의 변경 사항도 볼 수 있습니다. 사본도 영향을받습니다. 기본적으로 " 참조로 전달 "입니다.

그러나 컴퓨터에 .XLS 파일이 저장되어 있다고 가정하십시오. 당신은 그 파일을 친구에게 제공합니다. 이제 그가 해당 파일을 변경하는 경우 자신의 사본이있어 파일이 엉망이되지 않습니다. 기본적으로 " value by value "입니다. 신속한 놀이터 에서이 유추를 확인하기 위해 이미 여러 개의 간단한 프로그램이 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.