2015-02-02 4 views
0

Swift를 시작합니다. 필자의 이전 프로그래밍 배경은 주로 파이썬이기 때문에 스위프트에서 Pythonic 코딩 방법을 검색하는 경향이 있습니다. 운좋게도 Python에서 영감을 받았습니다. 파이썬에는 특수 메소드를 사용하여 클래스의 연산자를 오버로드하는 매우 강력한 방법이 있습니다. Swift에서 연산자를 오버로드 할 수있는 특정 이름 공간에서 함수를 정의 할 수 있지만 특수 연산자를 사용하려는 경우 연산자를 클래스에 과부하 할 수있는 방법을 찾지 못했습니다.Swift에서 Python과 같은 연산자 오버로드

수정 - 예제 추가.

class Vector(object): 
    def __init__(self, *args): # Initializing a vector of random size 
     self.vector = tuple(args) 

    def __len__(self): # This sources the data to the built-in len() function 
     return len(self.vector) 

    def __getitem__(self, i): # Overloads [ ] operator 
     return self.vector[i] 

    def __add__(self, vector): # Overloads + operator 
     if len(self) != len(vector): 
      raise ValueError("Vectors should be of equal length") 
     return tuple([self.vector[i] + vector[i] for i in xrange(len(self))]) 


a, b = Vector(1, 2, 3, 4), Vector(2, 3, 4, 5) # My modified tuples 

print(a + b) # this operation is affected 
print((1, 2, 3, 4) + (2, 3, 4, 5)) # this is not, since these are standard tuples 

출력 : 여기

(3, 5, 7, 9) 
(1, 2, 3, 4, 2, 3, 4, 5) 

I 단지 의 getItem 방법을 정의하여, [상기 수단을 추가로 정의하는, 과부하 +하고있다. 이 클래스는 파이썬에서 터플 타입뿐만 아니라 이니셜 라이저로부터 [] 동작을 상속 받았다. 그러나 더 자세히 설명하기 위해 수동으로 만들었다. 오버로딩은 클래스에서 캡슐화되어 있으므로 모든 유형 및 클래스가 고유 한 특수 메소드를 정의하므로 일반 연산자 작동에 영향을주지 않습니다.

+0

그러면 파이썬으로 어떻게 완료되었는지 스위프트 전문가에게 속삭이는 것입니다. –

+0

일반적으로 스위프트의 연산자 오버로드는 항상 글로벌입니다. 가장 가까운 유형의 연산자 오버로드를 만드는 것입니다. 또한 Thomas가 지적한대로 모든 관련 정보를 제공하면 유용한 대답을 얻을 수 있습니다. –

+0

@ThomasKilian 방금 예제를 추가했습니다. –

답변

1

서로 다른 메커니즘을 사용하여 오버라이드되는 여러 연산자입니다. 따라서 흩어져 나는 일반적인로 구현했습니다

class Vector<T> { 
    let vector : [T] 

    init(values:[T]) { 
     vector = values 
    } 

    subscript(index:Int) -> T { 
     get { 
      return vector[index] 
     } 
    } 

    func len() -> Int { 
     return vector.count 
    } 
} 

protocol Addable { 
    func +(lhs:Self, rhs:Self) -> Self 
} 

func + <T:Addable>(left:Vector<T>, right:Vector<T>) -> Vector<T> { 
    var result = [T]() 

    assert(left.len() == right.len(), "vectors should be of equal length") 
    for i in 0 ..< left.len() { 
     result.append(left[i] + right[i]) 
    } 

    return Vector(values: result) 
} 

참고 : __getitem__의 등가 플러스 무시하려면 subscript을 무시하는 것입니다, 당신은 함께 당신이 바람, 글로벌 공간에 func +를 구현해야 . 또한 Addable 프로토콜을 구현하면서 사용하는 데이터 유형을 지정해야합니다. 그것은 간단합니다 같은 :

extension Int : Addable {} 

나는 또한 혜택을 훨씬의 모습 표준 배열 클래스 및 재정의 운영을 통해 사용할 수없는 당신의 벡터 클래스에 정말로 여기가 아니라고 지적하고 있습니다 : 어느 경우

func + <T:Addable>(left:Array<T>, right:Array<T>) -> Array<T> { 
    var result = [T]() 

    assert(left.len() == right.len(), "vectors should be of equal length") 
    for i in 0 ..< left.len() { 
     result.append(left[i] + right[i]) 
    } 

    return result 
} 

, 당신은 쉽게 배열 또는 인라인 + 연산자를 사용하여 벡터 중 하나에 벡터 연산을 수행 할 수 있습니다.

+0

벡터 클래스, 따라서 벡터화 된 합계 연산은 마음이 구운 첫 번째 예일뿐입니다. 그래서, 만약 내가 바로 그것을 얻을 수있는 모든 오버로드 함수가 다른 형식 유추를 가지고 하나의 코드에서 원하는대로 동일한 연산자를 여러 번 오버로드 할 수 있습니까? –

+1

예. 연산자 오버로딩은 신속한 함수 오버로드의 모든 일반 규칙의 적용을받습니다. 따라서 매개 변수 개수 및/또는 형식 또는 결과 형식이 달라야합니다. –

+0

고맙습니다. –