I have tried to calculate the area of a triangle using getter and setter with the help of formula area = (length * base)/2 using getter and setter
class Triangle {
var length: Double
var base:Double
var name:String
init(length: Double, base:Double, name:String ) {
self.length = length
self.name = name
self.base = base
}
var area: Double {
get { // getter
return base * length
}
set { //setter
area = newValue / 2.0
}
}
}
var triangle = Triangle(length:5,base:4,name:"f")
print(triangle.area)
The area returned should be 10 but it returns 20 i.e. the setter step is not getting called. The compiler is ignoring the setter step i.e. even if I comment-out the setter step, it makes no difference to the compiler. I want to use setter, how to go about it ?
It looks to me like area is a computed property. Shouldn't it be a read-only computed property? Seems to me that there are multiple triangles with a given area but different height/base values, so you can't set the area in a meaningful way.
var area: Double {
get { // getter
return 0.5 * base * length
}
}
You are also missing the /2 part of the area formula a = 1/2 b * h. That's why your result is 20 when it should be 10.
area is a computed variable. It doesn't store any value. So you have to save your newValue somewhere. E.g.,
class Triangle {
var length: Double
var base:Double
var name:String
init(length: Double, base:Double, name:String ) {
self.length = length
self.name = name
self.base = base
}
var area: Double {
get { // getter
return base * length
}
set { //setter
let tmpArea = newValue / 2.0
let squared = sqrt(tmpArea)
base = squared
length = squared
}
} }
Related
With this simple class I am getting the compiler warning
Attempting to modify/access x within its own setter/getter
and when I use it like this:
var p: point = Point()
p.x = 12
I get an EXC_BAD_ACCESS. How can I do this without explicit backing ivars?
class Point {
var x: Int {
set {
x = newValue * 2 //Error
}
get {
return x / 2 //Error
}
}
// ...
}
Setters and Getters apply to computed properties; such properties do not have storage in the instance - the value from the getter is meant to be computed from other instance properties. In your case, there is no x to be assigned.
Explicitly: "How can I do this without explicit backing ivars". You can't - you'll need something to backup the computed property. Try this:
class Point {
private var _x: Int = 0 // _x -> backingX
var x: Int {
set { _x = 2 * newValue }
get { return _x / 2 }
}
}
Specifically, in the 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
You can customize the set value using property observer. To do this use 'didSet' instead of 'set'.
class Point {
var x: Int {
didSet {
x = x * 2
}
}
...
As for getter ...
class Point {
var doubleX: Int {
get {
return x / 2
}
}
...
Setters/getters in Swift are quite different than ObjC. The property becomes a computed property which means it does not have a backing variable such as _x as it would in ObjC.
In the solution code below you can see the xTimesTwo does not store anything, but simply computes the result from x.
See Official docs on computed properties.
The functionality you want might also be Property Observers.
What you need is:
var x: Int
var xTimesTwo: Int {
set {
x = newValue / 2
}
get {
return x * 2
}
}
You can modify other properties within the setter/getters, which is what they are meant for.
To elaborate on GoZoner's answer:
Your real issue here is that you are recursively calling your 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
}
}
Like the code comment suggests above, you are infinitely calling the x property's getter, which will continue to execute until you get a EXC_BAD_ACCESS code (you can see the spinner in the bottom right corner of your Xcode's playground environment).
Consider the example from the Swift documentation:
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)
}
}
}
Notice how the center computed property never modifies or returns itself in the variable's declaration.
In order to override setter and getter for swift variables use the below given code
var temX : Int?
var x: Int?{
set(newX){
temX = newX
}
get{
return temX
}
}
We need to keep the value of variable in a temporary variable, since trying to access the same variable whose getter/setter is being overridden will result in infinite loops.
We can invoke the setter simply like this
x = 10
Getter will be invoked on firing below given line of code
var newVar = x
Update: Swift 4
In the below class setter and getter is applied to variable 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(newValue) { //setter
sideLength = newValue / 4.0
}
}
Creating object
var triangle = Triangle(sideLength: 3.9, name: "a triangle")
Getter
print(triangle.perimeter) // invoking getter
Setter
triangle.perimeter = 9.9 // invoking setter
You are recursively defining x with x. As if someone asks you how old are you? And you answer "I am twice my age". Which is meaningless.
You must say I am twice John's age or any other variable but yourself.
computed variables are always dependent on another variable.
The rule of the thumb is never access the property itself from within the getter ie get. Because that would trigger another get which would trigger another . . . Don't even print it. Because printing also requires to 'get' the value before it can print it!
struct Person{
var name: String{
get{
print(name) // DON'T do this!!!!
return "as"
}
set{
}
}
}
let p1 = Person()
As that would give the following warning:
Attempting to access 'name' from within it's own getter.
The error looks vague like this:
As an alternative you might want to use didSet. With didSet you'll get a hold to the value that is was set before and just got set to. For more see this answer.
Try using this:
var x:Int!
var xTimesTwo:Int {
get {
return x * 2
}
set {
x = newValue / 2
}
}
This is basically Jack Wu's answer, but the difference is that in Jack Wu's answer his x variable is var x: Int, in mine, my x variable is like this: var x: Int!, so all I did was make it an optional type.
Setters and getters in Swift apply to computed properties/variables. These properties/variables are not actually stored in memory, but rather computed based on the value of stored properties/variables.
See Apple's Swift documentation on the subject: Swift Variable Declarations.
Here is a theoretical answer. That can be found here
A { get set } property cannot be a constant stored property. It should be a computed property and both get and set should be implemented.
Update for Swift 5.1
As of Swift 5.1 you can now get your variable without using get keyword. For example:
var helloWorld: String {
"Hello World"
}
I don't know if it is good practice but you can do something like this:
class test_ancestor {
var prop: Int = 0
}
class test: test_ancestor {
override var prop: Int {
get {
return super.prop // reaching ancestor prop
}
set {
super.prop = newValue * 2
}
}
}
var test_instance = test()
test_instance.prop = 10
print(test_instance.prop) // 20
Read more
Given the below struct in Swift, is there a more concise way to alias the instance variables x, y, and z to the properties of the three-tuple, _v?
Note: I realize that, of course, I could just declare these instance variables as Doubles and not need the tuple. However, the reason I'm doing it this way is so I can set three variables with a single-line statement like you will see in the init method and the below sample code.
Sample code with desired output of "1.0" "4.0":
var myVector = Vector3([1.0,2.0,3.0])
let x = myVector.x
print(x)
myVector.v = (4.0,5.0,6.0)
print(x)
The class:
struct Vector3 {
typealias V3 = (x:Double,y:Double,z:Double)
var v:V3 = (x:0.0,y:0.0,z:0.0)
var x:Double {
get {
return v.x
}
set(x) {
v.x = x
}
}
var y:Double {
get {
return v.y
}
set(y) {
v.y = y
}
}
var z:Double {
get {
return v.z
}
set(z) {
v.z = z
}
}
init(_ args:AnyObject...) {
if(args[0].isKindOfClass(NSArray)) {
v = (args[0][0].doubleValue,args[0][1].doubleValue,args[0][2].doubleValue)
}
else if(args.count == 3){
v = (args[0].doubleValue,args[1].doubleValue,args[2].doubleValue)
}
}
}
What I would like to be able to do is:
struct Vector3 {
typealias V3 = (x:Double,y:Double,z:Double)
var v:V3 = (x:0.0,y:0.0,z:0.0)
alias x = v.x
alias y = v.y
alias z = v.z
init(_ args:AnyObject...) {
if(args[0].isKindOfClass(NSArray)) {
v = (args[0][0].doubleValue,args[0][1].doubleValue,args[0][2].doubleValue)
}
else if(args.count == 3){
v = (args[0].doubleValue,args[1].doubleValue,args[2].doubleValue)
}
}
}
Of course that doesn't work. But is there another way to achieve the same thing?
Just do the opposite!
I realize that, of course, I could just declare these instance variables as Doubles and not need the tuple. However, the reason I'm doing it this way is so I can set three variables with a single-line statement like you will see in the init method and the below sample code.
If this is the reason then just do the opposite
struct Vector3 {
var x: Double
var y: Double
var z: Double
var coordinates: (Double, Double, Double) {
set { (x, y, z) = newValue }
get { return (x, y, z) }
}
}
Usage
var vector = Vector3(x: 1, y: 2, z: 3)
vector.x = 4
vector.coordinates // (4, 2, 3)
Final note
Your initializer could be improved in several ways.
Stop using NSArray, you are using Swift not Objective-C
Stop using isKindOfClass, use as? to perform a conditional cast
You have faith the objects inside the first array/s will have a doubleValue property. So I could easily crash your init passing something different right?
Now my question
What's wrong with the memberwise struct initializer?
It is automatically generated when you don't explicitly define an initializer for a struct, like in my previous code snipped.
Are you sure you want to define an initializer that literally accept any sort of objects an will crash with 99.99% of the combinations of values someone can pass to it?
I have an Avatar struct. This struct has properties called elements that hold several parts of the face like Eyes, Mouth and so on. In the init(withGender: AvatarGender) method. I want all these elements to have their default to zero.
But instead of having zeros I get huge random Ints. I can't figure out why!
struct Avatar {
var gender: AvatarGender
var skin: AvatarSkinColor
var elements: [AvatarElement: Int]
var rawString: String {
// a computed property
}
init(withGender: AvatarGender) {
gender = withGender
skin = .White
elements = [AvatarElement: Int]()
var allElementsType = [AvatarElement]()
if gender == .Man {
allElementsType = AvatarElement.allMaleValues
} else if gender == .Woman {
allElementsType = AvatarElement.allFemaleValues
}
for element in allElementsType {
elements[element] = 0 // <= This doesn't work !!!
}
}
init(fromRawString: String) {
// Another init method that works properly
}
}
Above AvatarGender, AvatarSkinColor and AvatarElement are enums.
So I was playing around with protocol extensions and i ran into an "interesting" problem.
I wanted to write a Meters and Kilometers units type for testing some things out. Its VERY easy to do this as a class where there is a base class and both sub classes override the base, while just overriding a simple value
//Conversion factor between types
enum DISTANCE_UNIT_TYPE : Double {
case METER = 1.0;
case KILOMETER = 0.001;
}
protocol DistanceUnit {
var unitType : DISTANCE_UNIT_TYPE {get}
var value : Double { get set }
var baseValue : Double { get set }
}
struct Kilometers : DistanceUnit {
var unitType = DISTANCE_UNIT_TYPE.KILOMETER
var value : Double
var baseValue : Double
init(_ v : Double) {
value = v
baseValue = v * unitType.rawValue
}
}
struct Meters : DistanceUnit {
var unitType = DISTANCE_UNIT_TYPE.METER
var value : Double
var baseValue : Double
init(_ v : Double) {
value = v
baseValue = v * unitType.rawValue
}
}
So as you can see i have lots of duplicate code (specifically the initializers)
I tried to make a protocol extension to set the default initializer
extension DistanceUnit {
init(_ v : Double) {
value = v
baseValue = v * unitType.rawValue
}
}
but I get an error of variable 'self' passed by reference before being initalized
Is there any way to get this to work or do i just have to type lots of duplicate code? Maybe using unsafe or something?
I assume that fqdn is right and we won't be able to use custom inits inside protocols extension as we would like to, but only time will tell.
But there is still some workaround:
struct Meters : DistanceUnit {
var unitType = DISTANCE_UNIT_TYPE.METER
var value : Double
var baseValue : Double
init() { // this one is needed as designated initializer for your protocol extension
value = 0
baseValue = 0
}
}
protocol DistanceUnit {
var unitType : DISTANCE_UNIT_TYPE {get}
var value : Double { get set }
var baseValue : Double { get set }
init() // this is new and you will NEED to implement this in your structure or class
}
extension DistanceUnit {
init(_ v : Double) {
self.init()
value = v
baseValue = v * unitType.rawValue
}
// you can now implement a lot more different default inits and they should work fine here :)
// here is a quick example
init(_ s : String) {
self.init(Double(s.characters.count))
}
}
Hope that will help you. I learned this trick a few days ago when i was building a custom generic singleton generator with protocol extensions (see here).
With this simple class I am getting the compiler warning
Attempting to modify/access x within its own setter/getter
and when I use it like this:
var p: point = Point()
p.x = 12
I get an EXC_BAD_ACCESS. How can I do this without explicit backing ivars?
class Point {
var x: Int {
set {
x = newValue * 2 //Error
}
get {
return x / 2 //Error
}
}
// ...
}
Setters and Getters apply to computed properties; such properties do not have storage in the instance - the value from the getter is meant to be computed from other instance properties. In your case, there is no x to be assigned.
Explicitly: "How can I do this without explicit backing ivars". You can't - you'll need something to backup the computed property. Try this:
class Point {
private var _x: Int = 0 // _x -> backingX
var x: Int {
set { _x = 2 * newValue }
get { return _x / 2 }
}
}
Specifically, in the 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
You can customize the set value using property observer. To do this use 'didSet' instead of 'set'.
class Point {
var x: Int {
didSet {
x = x * 2
}
}
...
As for getter ...
class Point {
var doubleX: Int {
get {
return x / 2
}
}
...
Setters/getters in Swift are quite different than ObjC. The property becomes a computed property which means it does not have a backing variable such as _x as it would in ObjC.
In the solution code below you can see the xTimesTwo does not store anything, but simply computes the result from x.
See Official docs on computed properties.
The functionality you want might also be Property Observers.
What you need is:
var x: Int
var xTimesTwo: Int {
set {
x = newValue / 2
}
get {
return x * 2
}
}
You can modify other properties within the setter/getters, which is what they are meant for.
To elaborate on GoZoner's answer:
Your real issue here is that you are recursively calling your 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
}
}
Like the code comment suggests above, you are infinitely calling the x property's getter, which will continue to execute until you get a EXC_BAD_ACCESS code (you can see the spinner in the bottom right corner of your Xcode's playground environment).
Consider the example from the Swift documentation:
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)
}
}
}
Notice how the center computed property never modifies or returns itself in the variable's declaration.
In order to override setter and getter for swift variables use the below given code
var temX : Int?
var x: Int?{
set(newX){
temX = newX
}
get{
return temX
}
}
We need to keep the value of variable in a temporary variable, since trying to access the same variable whose getter/setter is being overridden will result in infinite loops.
We can invoke the setter simply like this
x = 10
Getter will be invoked on firing below given line of code
var newVar = x
Update: Swift 4
In the below class setter and getter is applied to variable 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(newValue) { //setter
sideLength = newValue / 4.0
}
}
Creating object
var triangle = Triangle(sideLength: 3.9, name: "a triangle")
Getter
print(triangle.perimeter) // invoking getter
Setter
triangle.perimeter = 9.9 // invoking setter
You are recursively defining x with x. As if someone asks you how old are you? And you answer "I am twice my age". Which is meaningless.
You must say I am twice John's age or any other variable but yourself.
computed variables are always dependent on another variable.
The rule of the thumb is never access the property itself from within the getter ie get. Because that would trigger another get which would trigger another . . . Don't even print it. Because printing also requires to 'get' the value before it can print it!
struct Person{
var name: String{
get{
print(name) // DON'T do this!!!!
return "as"
}
set{
}
}
}
let p1 = Person()
As that would give the following warning:
Attempting to access 'name' from within it's own getter.
The error looks vague like this:
As an alternative you might want to use didSet. With didSet you'll get a hold to the value that is was set before and just got set to. For more see this answer.
Try using this:
var x:Int!
var xTimesTwo:Int {
get {
return x * 2
}
set {
x = newValue / 2
}
}
This is basically Jack Wu's answer, but the difference is that in Jack Wu's answer his x variable is var x: Int, in mine, my x variable is like this: var x: Int!, so all I did was make it an optional type.
Setters and getters in Swift apply to computed properties/variables. These properties/variables are not actually stored in memory, but rather computed based on the value of stored properties/variables.
See Apple's Swift documentation on the subject: Swift Variable Declarations.
Here is a theoretical answer. That can be found here
A { get set } property cannot be a constant stored property. It should be a computed property and both get and set should be implemented.
Update for Swift 5.1
As of Swift 5.1 you can now get your variable without using get keyword. For example:
var helloWorld: String {
"Hello World"
}
I don't know if it is good practice but you can do something like this:
class test_ancestor {
var prop: Int = 0
}
class test: test_ancestor {
override var prop: Int {
get {
return super.prop // reaching ancestor prop
}
set {
super.prop = newValue * 2
}
}
}
var test_instance = test()
test_instance.prop = 10
print(test_instance.prop) // 20
Read more