When I try to create an instance of Monster class the print function doesn't seem to do anything. Why is that? I'm working with unity 4 if that's of any help. Also I cannot make a Monster class instance without using var, despite it being optional(allegedly).
function Update () {
var mon = Monster("Torreadore");
mon2 = Monster("blueberry"); //unknown identifier : 'mon2'
//even though it's been said that var is optional in the js tutorial
}
class Monster
{
var name : String;
function Monster(n : String)
{
name = n;
print(name + " has been created.");
}
}
Related
Problem is the following compiler error:
"Instance member 'name' cannot be used on type 'Person'"
class Person {
var name: String = "Amir"
var myClosure = { (family: String) -> Void in
print(name + " " + family)
}
func myFunc(family: String) -> Void {
print(name + " " + family)
}
}
The code inside myFunc and myClosure are the same, but I have compiler error on myClosure definition.
As I know, basically closures and functions are the same. So what difference between them make the above limitation for closures?
The problem is that I'm trying to initialize a variable using an instance's variable while the instance itself has not been created yet.
So the problem is not related to closure nature. The same problem does exist in the following code where I'm trying to initialize nickname with name instance property.
class Person {
var name: String = "Amirreza"
var nickname: String = name
}
As compiler says, "property initializers run before 'self' is available", so in the above code the self.name is not available to initialize nickname and this is the source of the problem.
Here the solution is to use "lazy" keyword before nickname definition. The lazy keywork defers the initialization of the nickname property to when it is accessed for the first time. Means when we are sure that the instance has been created and name property is available.
To read more about lazy refer to https://docs.swift.org/swift-book/LanguageGuide/Properties.html
So the correct form of above code is:
class Person {
var name: String = "Amirreza"
lazy var nickname: String = name
}
And the correct form of the my main question code would be:
class Person {
var name: String = "Amirreza"
lazy var myClosure = { [weak self] (family: String) -> Void in
print(self!.name + " " + family)
}
func myFunc(family: String) -> Void {
print(self.name + " " + family)
}
}
Just note that we have to refer to properties inside closures with self explicitly like self.name. Meanwhile to avoid strong reference cycles we need to define a capture list in closure definition which in my example is [weak self].
By defining self as 'weak', self turns to an optional variable, so we have to unwrap it somehow which makes me to write self!.name in the closure.
I was doing some research about the reasons we should use Get and Set for our properties.
I've noticed 3 main reasons for it
When you want to do/check something before you actually set the
property
When you want to have a property that you can only Get from it
(maybe for security purposes I guess? ), or give it different access
levels.
Hiding the internal representation of the property while exposing a
property using an alternative representation. (which for me doesn't
make a lot of sense since i can access it on the wrong place using
the Set function anyways)
The code below is a example of how you would implement Get and Set for properties in Swift, taking advantage of those 3 points I mentioned:
class Test
{
private var _testSet:String!
private var _testGetOnly:String
var testSet:String{
get{
return _testSet
}
set{
_testSet = newValue + "you forgot this string"
}
}
var testGetOnly:String!{
get{
return _testGetOnly
}
}
init(testSet:String, testGetOnly:String)
{
_testSet = testSet
_testGetOnly = testGetOnly
}
}
But this other example below also take advantage of those points mentioned but instead of using another computed property to return the private property value I just use the willSet and didSet observers
class Test
{
var testGet:String {
willSet{
fatalError("Operation not allowed")
}
}
var testWillSet:String!{
didSet{
self.testWillSet = self.testWillSet + "you forgot this string"
}
}
init(testGet:String, testWillSet:String)
{
self.testGet = testGet
self.testWillSet = testWillSet
}
}
So I'm curious to know what are the ADVANTAGES and DISADVANTAGES of each implementation.
Thanks in advance
Your question boils down to compile time vs. run time error. To address your 3 questions:
Yes, willCheck is your only option here
Readonly properties fall into 2 types: (a) those whose value derive from other properties, for example, their sum; and (b) those that you want to be able to change by yourself, but not by the users. The first type truly have no setter; the second type has a public getter and a private setter. The compiler can help you check for that and the program will not compile. If you throw a fatalError in didSet you get a runtime error and your application will crash.
There can be state objects that you don't want the user to freely mess with, and yes, you can completely hide those from the users.
Your code first example was too verbose in defining the backing variables - you don't need to do that. To illustrate these points:
class Test
{
// 1. Validate the new value
var mustBeginWithA: String = "A word" {
willSet {
if !newValue.hasPrefix("A") {
fatalError("This property must begin with the letter A")
}
}
}
// 2. A readonly property
var x: Int = 1
var y: Int = 2
var total: Int {
get { return x + y }
}
private(set) var greeting: String = "Hello world"
func changeGreeting() {
self.greeting = "Goodbye world" // Even for private property, you may still
// want to set it, just not allowing the user
// to do so
}
// 3. Hide implementation detail
private var person = ["firstName": "", "lastName": ""]
var firstName: String {
get { return person["firstName"]! }
set { person["firstName"] = newValue }
}
var lastName: String {
get { return person["lastName"]! }
set { person["lastName"] = newValue }
}
var fullName: String {
get { return self.firstName + " " + self.lastName }
set {
let components = newValue.componentsSeparatedByString(" ")
self.firstName = components[0]
self.lastName = components[1]
}
}
}
Usage:
let t = Test()
t.mustBeginWithA = "Bee" // runtime error
t.total = 30 // Won't compile
t.greeting = "Goodbye world" // Won't compile. The compiler does the check for you
// instead of a crash at run time
t.changeGreeting() // OK, greeting now changed to "Goodbye world"
t.firstName = "John" // Users have no idea that they are actually changing
t.lastName = "Smith" // a key in the dictionary and there's no way for them
// to access that dictionary
t.fullName = "Bart Simpsons" // You do not want the user to change the full name
// without making a corresponding change in the
// firstName and lastName. With a custome setter, you
// can update both firstName and lastName to maintain
// consistency
A note about private in Swift 2 vs. Swift 3: if you try this in a Swift 2 playground, you will find t.greeting = "Goodbye world" works just fine. This is because Swift 2 has a strange access level specifier: private means "only accessible within the current file". Separate the class definition and the sample code into different files and Xcode will complain. In Swift 3, that was changed to fileprivate which is both clearer and save the private keyword for something more similar to to Java and .NET
This question already has an answer here:
Swift: Failed to assign value to a property of protocol?
(1 answer)
Closed 6 years ago.
Can someone please tell me why Swift has to call the setter of a property when it's only being used to access an object (a protocol) in order to set one of its properties? This first example shows the error I get if I don't declare the indirect object as settable:
protocol AProtocol {
var name: String { get set }
}
class AnImplementation: AProtocol {
var name = ""
}
class AParent {
var test = AnImplementation()
}
class AChild {
var parent: AParent!
var test: AProtocol {
get { return parent.test }
// Note: Not settable
}
}
var parent = AParent()
var child = AChild()
child.parent = parent
child.test.name = "Hello world!" // Error: Cannot assign to property : 'test' is a get-only property
print(child.test.name)
If I give it a setter, it compiles and works but it calls the setter:
protocol AProtocol {
var name: String { get set }
}
class AnImplementation: AProtocol {
var name = ""
}
class AParent {
var test = AnImplementation()
}
class AChild {
var parent: AParent!
var test: AProtocol {
get { return parent.test }
set(newTest) { print("Shouldn't be here!") }
}
}
var parent = AParent()
var child = AChild()
child.parent = parent
child.test.name = "Hello world!"
print(child.test.name)
Output is:
Shouldn't be here!
Hello world!
I'm not sure what I'm not understanding here. I assume I can just give it an empty setter, but I'd like to understand the reason for it.
Any information is much appreciated!
Change your protocol declaration to this:
protocol AProtocol:class {
var name: String { get set }
}
Otherwise, it is taken by default as a value type. Changing a value type's property replaces the value type instance (as shown by the setter observer). And you can't do that if the reference is a let reference.
This is probably caused by the fact that the compiler doesn't know whether AChild.test is a class or a value type. With classes there is no problem but with value types assigning to name would also create an assignment to test (value-copy behavior). Marking APProtocol as class protocol will fix the problem.
To expand, when the compiler is not sure whether test is a value or a class type, it will use the following rewrite of child.test.name = "Hello world!":
var tmp = child.test
tmp.test = "Hello world!"
child.test = tmp
because that will work for both class and value types.
I have been updating my game recently to use more value types. I am still not 100% confident with weak and unowned in some cases so I went the struct way to avoid strong reference cycles. As per apples newer keynotes it seems value types are they way to go for the most part anyway.
I have never seen an example where structs are used to render sprites in a spriteKit game so I wonder what the drawbacks are.
I understand that they are copied and not referenced but for my usage it seems to work.
So basically is there something I need to watch out for when doing this
struct Flag {
let post: SKSpriteNode
let flag: SKSpriteNode
init(postImage: String, flagImage: String) {
post = SKSpriteNode(imageNamed: postImage)
// other set ups for post sprite
flag = SKSpriteNode(imageNamed: flagImage)
// other set ups for flag sprite
post.addChild(flag)
}
func animate() {
// code to animate flag
}
}
Than in my SKScenes I simply add them as usual
let flag = Flag(postImage: "FlagPostImage", flagImage: "FlagImage")
flag.post.position = ...
addChild(flag.post)
flag.animate()
Now even if I create multiple flags in the same scene I seem to have no problems with this way.
I am just curious because I have never really seen an example like this so I wonder if I am missing something, like performance drawbacks etc.
Thanks for any help.
Personally I avoid creating Structs that contain Classes. Because Structs copy, each and every copy that get's passed around your app will increase the reference count of the Classes. This makes it harder to manage them instead of easier.
It is also useful to take a look at how UIKit uses Structs. A UIView is an object but has many defining properties that are Structs. For example it's frame.
Drop the code below in a playground to see some effects of this behaviour.
The protocol is just to get some meaningful feedback form the playground.
protocol IDLookable : CustomPlaygroundQuickLookable {
var id : Int { get set }
}
extension IDLookable {
func customPlaygroundQuickLook() -> PlaygroundQuickLook {
return PlaygroundQuickLook.AttributedString(NSAttributedString(string: "\(self.dynamicType) with id : \(self.id)"))
}
}
class MyClass : IDLookable {
var id : Int = 0
init(id : Int) {
self.id = id
}
}
struct MyContainerStruct : IDLookable {
var id : Int = 0
var object : MyClass
init(id : Int, object:MyClass) {
self.id = id
self.object = object
}
}
class Scope {
// ref count = 1
var object = MyClass(id: 11)
var structContainer : MyContainerStruct
init() {
// ref count = 2
structContainer = MyContainerStruct(id: 222, object: object)
messWithAClassInAStruct()
}
func messWithAClassInAStruct() {
// ref count = 3
var structContainerTwo = structContainer
structContainerTwo.id = 333
structContainerTwo.object // 11
// altering the object in one struct will obvously update all references
structContainerTwo.object.id = 1
structContainer.object // 1
structContainerTwo.object // 1
}
}
let test = Scope()
One pattern that does make it easy to work with Reference Types in Value Types is to store them as weak optionals in the Value Types. This means that something will need to have a strong reference but chances are that some Class will be responsible for creating the Structs this is a good place to keep that strong reference.
struct MyContainerStruct : IDLookable {
var id : Int = 0
weak var object : MyClass?
init(id : Int, object:MyClass) {
self.id = id
self.object = object
}
}
class Scope {
// ref count = 1
var object = MyClass(id: 11)
var structContainer : MyContainerStruct
init() {
// ref count = 1
structContainer = MyContainerStruct(id: 222, object: object)
messWithAClassInAStruct()
}
func messWithAClassInAStruct() {
// ref count = 1
var structContainerTwo = structContainer
structContainerTwo.id = 333
structContainerTwo.object // 11
}
}
let test = Scope()
I am having an issue with calling an instance method within the class itself. If someone can provide me some insight it would be greatly appreciated.
My current code looks like this:
class Rect
{
func printthis() -> String {
return "this is working or what"
}
var toPrint:String = self.printthis()
}
The error I am getting in Xcode is: Use of unresolved identifier 'self'.
What am I missing here?
You can't call an instance method without an instance. The class is merely the template for instances. So i don't what you are trying to do here...
But the answer is no, you cannot call an instance method form the class definition because there is no instance yet.
Perhaps you want to delcare a class method and use that to set an instance variable on creation? If so, you might do that like this:
class Rect {
class func printthis() -> String {
return "this is working or what"
}
var toPrint:String
init() {
toPrint = Rect.printthis()
}
}
var r = Rect()
println(r.toPrint) //-> this is working or what
An instance of a class is not initialized and able to be referenced (even as 'self') until all of its variables have been assigned values.
An option that may work for you is to declare your variable as an implicitly-unwrapped optional, which is assigned nil by default. Then in the class's init method, since all of the variables have been assigned values, you are able to start calling methods on your instance.
class Rect {
var toPrint: String!
init() {
toPrint = printthis()
}
printthis() -> String {
return "this will work"
}
}
the problem is that swift is strict about initing all properties.
you may as a workaround
class Rect
{
func printthis() -> String {
return "this is working or what"
}
var toPrint:String = ""
init() {
toPrint = printthis()
}
}