如何使用mutating get实现只读var

时间:2016-04-27 14:27:06

标签: swift

我有一个var

using UnityEngine;
using UnityEngine.EventSystems;

//i chose box collider because its cheap
[RequireComponent(typeof(BoxCollider))]
public class RenderTextureRaycaster : MonoBehaviour, IPointerDownHandler {

    //assign in inspector
    public Camera portalExit;

    BoxCollider portal;
    Vector3 portalExitSize;

    void Start() {
        portal = GetComponent<BoxCollider>();
        //this is the target camera resolution, idk if there is another way to get it.
        portalExitSize = new Vector3(portalExit.targetTexture.width, portalExit.targetTexture.height, 0);
    }

    public void OnPointerDown(PointerEventData eventData) {
        //the click in world space
        Vector3 worldClick = eventData.pointerCurrentRaycast.worldPosition;
        //transformed into local space
        Vector3 localClick = transform.InverseTransformPoint(worldClick);
        //since the origin of the collider is in its center, we need to offset it by half its size to get it realtive to bottom left
        Vector3 textureClick = localClick + portal.size / 2;
        //now we scale it up by the actual texture size which equals to the "camera resoution"
        Vector3 rayOriginInCameraSpace = Vector3.Scale(textureClick, portalExitSize);

        //with this knowledge we can creata a ray.
        Ray portaledRay = portalExit.ScreenPointToRay(rayOriginInCameraSpace );
        RaycastHit raycastHit;

        //and cast it.
        if (Physics.Raycast(portaledRay, out raycastHit)) {
            Debug.DrawLine(portaledRay.origin, raycastHit.point, Color.blue, 4);
        }
        else {
            Debug.DrawRay(portaledRay.origin, portaledRay.direction * 100, Color.red, 4);
        }
    }
}

我不需要设置,只有得到, 但我需要做这样的事情

var soketTasksList:Set<SocketTask> {
   get { return socketManager.tasksList }
}

但是编译器说

  

不能在不可变值上使用mutating成员是get-only属性

我尝试在get中添加关键字'mutating',但这不起作用。我也 试图在var中添加“mutating”,但这也不起作用。

UPD 我不明白为什么我需要设置? 如果我做了

soketTasksList.remove(task)

我可以

func getSoketTasksList() -> Set<CXSocketTask> {
    return socketManager.tasksList
}

为什么不用var?

3 个答案:

答案 0 :(得分:3)

  

我不需要设置,只需要

是的,你需要设置。

  

我需要做这样的事情soketTasksList.remove(task)

这是一个突变。变异value type like Set需要设置的能力。但是你已经把它作为一个只读的计算变量来切断这种可能性。

  UPD我不明白为什么我需要设置?如果我做了

   func getSoketTasksList() -> Set<CXSocketTask> {
       return socketManager.tasksList
   }
     

我可以

   getSoketTasksList().remove(task)

不,你不能。试试吧。这是一个游乐场测试:

class CXSocketTask:NSObject{}
class SocketManager {
    var tasksList = Set<CXSocketTask>()
}
let task = CXSocketTask()
let socketManager = SocketManager()
socketManager.tasksList.insert(task)

func getSoketTasksList() -> Set<CXSocketTask> {
    return socketManager.tasksList
}
getSoketTasksList().remove(task)

最后一行生成错误:“不能对不可变值使用变异成员:'getSoketTasksList'返回不可变值”。

答案 1 :(得分:0)

您可以将临时变量用于此目的:

var list = soketTasksList
list.remove(task)

请注意,基础列表(在这种情况下为socketManager.tasksList)保持不变。

答案 2 :(得分:0)

唯一可行的方法是通过可设置的方式进行实际的变异。

例如:

struct Person {
  var age: Int = 1

  mutating func setAge(a: Int) -> Int {
    age = a
    return a
  }

  var computedAge: Int {
    mutating get {
      setAge(a: 4)
      return age
    }
  }
}

var person = Person()
print(person.computedAge) //Prints 4

这是设计使然