物业获取者和二传手

 leedaning 发布于 2023-01-11 19:06

有了这个简单的类,我得到编译器警告

试图x在自己的setter/getter中修改/访问

当我像这样使用它时:

var p: point = Point()
p.x = 12

我得到一个EXC_BAD_ACCESS.如果没有明确支持ivars,我怎么能这样做?

class Point {

    var x: Int {
        set {
            x = newValue * 2 //Error
        }
        get {
            return x / 2 //Error
        }
    }
    // ...
}

GoZoner.. 220

塞特犬和吸气者适用于computed properties; 这样的属性在实例中没有存储 - 来自getter的值意味着从其他实例属性计算.在您的情况下,没有x分配.

明确地说:"如果没有明确的支持ivars我怎么能这样做".你不能 - 你需要一些东西来备份计算属性.试试这个:

class Point {
  private var _x: Int = 0             // _x -> backingX
  var x: Int {
    set { _x = 2 * newValue }
    get { return _x / 2 }
  }
}

具体来说,在Swift REPL中:

 15> var pt = Point()
pt: Point = {
  _x = 0
}
 16> pt.x = 10
 17> pt
$R3: Point = {
  _x = 20
}
 18> pt.x
$R4: Int = 10


Jack.. 104

Swift中的Setter/getters与ObjC完全不同.该属性变成了计算的属性,这意味着它具有背衬变量如_x因为它会在ObjC.

在上述方案中的代码下面你可以看到xTimesTwo没有存储任何东西,而是简单地计算从结果x.

请参阅有关计算属性的官方文档.

您想要的功能也可能是Property Observers.

你需要的是:

var x: Int

var xTimesTwo: Int {
    set {
       x = newValue / 2
    }
    get {
        return x * 2
    }
}

您可以修改setter/getters中的其他属性,这就是它们的用途.

8 个回答
  • 塞特犬和吸气者适用于computed properties; 这样的属性在实例中没有存储 - 来自getter的值意味着从其他实例属性计算.在您的情况下,没有x分配.

    明确地说:"如果没有明确的支持ivars我怎么能这样做".你不能 - 你需要一些东西来备份计算属性.试试这个:

    class Point {
      private var _x: Int = 0             // _x -> backingX
      var x: Int {
        set { _x = 2 * newValue }
        get { return _x / 2 }
      }
    }
    

    具体来说,在Swift REPL中:

     15> var pt = Point()
    pt: Point = {
      _x = 0
    }
     16> pt.x = 10
     17> pt
    $R3: Point = {
      _x = 20
    }
     18> pt.x
    $R4: Int = 10
    

    2023-01-11 19:07 回答
  • 你是递归定义xx.好像有人问你你多大了?你回答"我是我的两倍".这没有意义.

    你必须说我是约翰的年龄或任何其他变量,你自己.

    计算变量总是依赖于另一个变量.


    拇指法则是永远不会从访问属性本身的吸气剂,即get.因为这会触发另一个get会触发另一个...甚至不打印.因为打印还需要在打印之前"获取"该值!

    struct Person{
        var name: String{
            get{
                print(name) // DON'T do this!!!!
                return "as"
            }
            set{
            }
        }
    }
    
    let p1 = Person()
    

    因为这会发出以下警告:

    试图从它自己的getter中访问'name'.

    该错误看起来像这样模糊:

    在此输入图像描述

    作为替代方案,您可能想要使用didSet.随着didSet你将保持之前设置的值,并设置为.欲了解更多看到这个答案.

    2023-01-11 19:07 回答
  • 试试这个:

    var x:Int!
    
    var xTimesTwo:Int {
        get {
            return x * 2
        }
        set {
            x = newValue / 2
        }
    }
    

    这基本上就是Jack Wu的答案,但不同的是,在Jack Wu的回答中,他的x变量是var x: Int,在我的中,我的x变量是这样的:var x: Int!所以我所做的只是让它成为一个可选类型.

    2023-01-11 19:07 回答
  • 详细说明GoZoner的答案:

    这里你真正的问题是你递归地调用你的getter.

    var x:Int
        {
            set
            {
                x = newValue * 2 // This isn't a problem
            }
            get {
                return x / 2 // Here is your real issue, you are recursively calling 
                             // your x property's getter
            }
        }
    

    就像上面的代码注释所示,你无限地调用x属性的getter,它将继续执行,直到你得到一个EXC_BAD_ACCESS代码(你可以在Xcode的游乐场环境的右下角看到微调器).

    考虑一下Swift文档中的示例:

    struct Point {
        var x = 0.0, y = 0.0
    }
    struct Size {
        var width = 0.0, height = 0.0
    }
    struct AlternativeRect {
        var origin = Point()
        var size = Size()
        var center: Point {
            get {
                let centerX = origin.x + (size.width / 2)
                let centerY = origin.y + (size.height / 2)
                return Point(x: centerX, y: centerY)
            }
            set {
                origin.x = newValue.x - (size.width / 2)
                origin.y = newValue.y - (size.height / 2)
            }
        }
    }
    

    注意中心计算属性永远不会在变量的声明中修改或返回自身.

    2023-01-11 19:07 回答
  • 为了覆盖settergetter快速变量,使用下面给出的代码

    var temX : Int? 
    var x: Int?{
    
        set(newX){
           temX = newX
        }
    
        get{
            return temX
        }
    }
    

    我们需要将变量的值保存在临时变量中,因为尝试访问其getter/setter被覆盖的同一变量将导致无限循环.

    我们可以像这样调用setter

    x = 10
    

    在给定的代码行下面将触发Getter

    var newVar = x
    

    2023-01-11 19:07 回答
  • Swift中的Setter/getters与ObjC完全不同.该属性变成了计算的属性,这意味着它具有背衬变量如_x因为它会在ObjC.

    在上述方案中的代码下面你可以看到xTimesTwo没有存储任何东西,而是简单地计算从结果x.

    请参阅有关计算属性的官方文档.

    您想要的功能也可能是Property Observers.

    你需要的是:

    var x: Int
    
    var xTimesTwo: Int {
        set {
           x = newValue / 2
        }
        get {
            return x * 2
        }
    }
    

    您可以修改setter/getters中的其他属性,这就是它们的用途.

    2023-01-11 19:07 回答
  • 更新:Swift 4

    在下面的类中,setter和getter应用于变量 sideLength

    class Triangle: {
        var sideLength: Double = 0.0
    
        init(sideLength: Double, name: String) { //initializer method
            self.sideLength = sideLength
            super.init(name: name)
            numberOfSides = 3
        }
    
        var perimeter: Double {
            get { // getter
                return 3.0 * sideLength
            }
            set { //setter
                sideLength = newValue / 4.0
            }
       }
    

    创建对象

    var triangle = Triangle(sideLength: 3.9, name: "a triangle")
    

    消气

    print(triangle.perimeter) // invoking getter
    

    二传手

    triangle.perimeter = 9.9 // invoking setter
    

    2023-01-11 19:08 回答
  • 您可以使用属性观察器自定义设置值.要做到这一点,请使用'didSet'而不是'set'.

    class Point {
    
    var x: Int {
        didSet {
            x = x * 2
        }
    }
    ...
    

    至于吸气...

    class Point {
    
    var doubleX: Int {
        get {
            return x / 2
        }
    }
    ...
    

    2023-01-11 19:08 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有