Perhaps I am simply reading old material, but I can't see a way to do something seemingly very simple.
I have a class called Robot, each instance of which needs a unique id. The id is simply an Int that should be 1,2,3... The normal solution would be to have a class var MaxId that you increment in the init() and then assign that to the instance's id.
Swift (4?) does not have class vars, but does have computed properties at the class level. However, I am a bit mystified about how one might use this to do a MaxId. Am I missing something blindingly obvious here?
a unique id. The id is simply an Int that should be 1,2,3.
You can certainly use a static property and increment it, but note that
those are two different requirements. If all you really want is a unique id, there is no need for the “least available integer” approach. Just use the built-in UUID struct and move on.
Static variables are essentially class variables. Try this in a playground:
class Numbered {
static var serial: Int = 1
let myID: Int
init() {
myID = Numbered.serial
Numbered.serial = Numbered.serial + 1
}
}
print(Numbered().myID)
print(Numbered().myID)
Related
1.
According to the swift API design guidelines, a boolean property should read as assertions
> Uses of Boolean methods and properties should read as assertions about
the receiver when the use is nonmutating,
e.g. x.isEmpty, line1.intersects(line2).
2.
I would like to make a computed property of which type is Boolean to the existing data type.
Here is a simplified version of my code:
struct State {
var authorID: String
var myID: String
var `XXX`: Bool {
return myID == authorID
}
}
I want the property XXX to stand for whether I am author or not.
I firstly came up with the names like authorIsMe, iAmAuthor, isAuthorMe, etc. but realized that it didn’t read as assertions about the receiver.
So, what name do you think fit best for XXX? Any idea will be appreciated.
Thank you
(Please do not consider inlining the expression myID == authorID because in the original code, it is not short as above so I need the computed property)
amITheAuthor is the best property name according to me as it will clearly throw the answer & its means of use , its a suggestion you can use this as well.
I get an error when I put the type and size of an array of classes
I have tried:
fun main(args :Array<String>) {
class modul() {
var nommodul: String? = null
var coeff: Int? = null
var note: Int? = null
}
var releve
class notes() {
var releve: array<modul>(10){""} here the erreur
}
}
First of all, your code has several errors. This might be an MCVE and/or copy-paste issue, but I need to address these before I get started on the arrays.
var releve before the notes class isn't allowed. You don't assign it, you don't declare a type, and the compiler will complain if you copy-paste the code from your question.
Second, the array var itself: Array is upper-case, and initialization is separate. This would be more valid (note that this still does not work - the solution for that comes later in this answer):
var releve: Array<modul> = Array(10) {...}
// or
var releve = Array<modul>(10) {...}
And the last thing before I start on the array itself: please read the language conventions, especially the naming ones. Your classes should all start with an upper-case letter.
Kotlin arrays are quite different from Java arrays in many ways, but the most notable one being that direct array initialization also requires an initializer.
The brackets are expected to create a new instance, which you don't. You create a String, which isn't, in your case, a modul.
There are several ways to fix this depending on how you want to do this.
If you have instances you want to add to the array, you can use arrayOf:
arrayOf(modulInstance, modulInstance2, ...)
If you want to create them directly, you can use your approach:
var releve = Array(10) { modul() }
A note about both of these: because of the initialization, you get automatic type inference and don't need to explicitly declare <modul>
If you want Java-style arrays, you need an array of nulls.
There's two ways to do this:
var releve = arrayOfNulls<modul>(10)
// or
var releve = Array<modul?>(10) { null }
I highly recommend the first one, because it's cleaner. I'm not sure if there's a difference performance-wise though.
Note that this does infer a nullable type to the array, but it lets you work with arrays in a similar way to Java. Initialization from this point is just like Java: releve[i] = modul(). This approach is mostly useful if you have arguments you want to add to each of the classes and you need to do so manually. Using the manual initializers also provides you with an index (see the documentation) which you can use while initializing.
Note that if you're using a for loop to initialize, you can use Array(10) { YourClass() } as well, and use the supplied index if you need any index-sensitive information, such as function arguments. There's of course nothing wrong with using a for loop, but it can be cleaner.
Further reading
Array
Lambdas
here some example of kotlin array initialization:
array of Library Method
val strings = arrayOf("January", "February", "March")
Primitive Arrays
val numbers: IntArray = intArrayOf(10, 20, 30, 40, 50)
Late Initialization with Indices
val array = arrayOfNulls<Number>(5)
for (i in array.indices) {
array[i] = i * i
}
See Kotlin - Basic Types for details
In swift, is there anyway I can create a shared class? That is, say there is a class called Value:
class Value{
var a = 0
}
I want to use this class to be shared among different object instances.
For example,
class Main{
func main(){
print(Value.a)
Value.a++
}
}
class OtherClass{
func otherMain(){
print(Value.a)
Value.a++
}
}
let main = Main()
let other = OtherClass()
//I want this call to print 0
main.main()
//I want this call to print 1
other.otherMain()
I tried static on var a, but then it won't let me do arithmetics such as addition... But it is working if I change the Value into static instead of class. I thought only difference between struct and class was either variable type or reference type...
I'll appreciate to any help. Thanks
The best way to go about what you want to do, unfortunately, is not to do it at all. It seems that the architecture you're designing is quite fragile and two independent classes shouldn't depend on a shared object state and if they do, they should be related via class inheritance or protocols.
A better solution would be:
class MyClass {
static var a = 0
}
class SubclassA: MyClass {
func someFunc() {
print(self.dynamicType.a)
self.dynamicType.a += 1
}
}
class SubclassB: MyClass {
func otherFunc() {
print(self.dynamicType.a)
}
}
There's a few reasons you should do it this way, over your previous solution:
Your shared state can stay private to those two classes. No one outside of those classes can or should modify that value.
Singleton patterns while sometimes useful, have a bunch of problems. This article explains it better than I can.
You have to think of your application and your code architecture as a state machine, moving from one state to another. The goal is to write code that's reusable, modular, generic, and has as little state as possible. The more stateless your code, the better. That's the whole idea behind platforms like ReactJS and ReactiveCocoa; they help simplify that application state.
What you might be looking for is data persistence, something like Realm or CoreData, where you persist data to disk and then you can read it back at a later time as needed. Imagine for example that instead of an Int your shared state was an array of UIImages. With the singleton pattern, you're keeping those images in memory at all times. What if the list grows to be 200 or 300 in length? Then you have memory issues.
I have a model class in Swift, whose primary purpose is to contain an array of custom objects, but also has other methods/properties etc.
public class Budget: NSObject, NSCoding {
var lineItems : [LineItem] = []
// Other methods
// Other properties
}
As I understand it, it's best practice to not make the property publicly settable, but I want it to be testable, so lineItems needs to be publicly gettable.
Reading the docs, I could do this:
private(set) public var lineItems : [LineItem] = []
But then I have to write a lot of boilerplate code to recreate array methods, such as insert, removeAtIndex etc.
What is best practice here? At the moment, I don't need to do anything else on insert/removal of items, but I guess I may need to do validation or similar in future, but even so it seems redundant to have to write code that just recreates Array methods.
Would it be better just to make lineItems publicly gettable and settable? Are their circumstances where this would or wouldn't make sense?
Thanks!
Swift's Array is a (immutable) value type, which means that
var a = ["object"]
var b = [String]()
b.append("object")
b == a // true
From this point of view it does not make sense to allow modifying an array and not allow setting it - modifying is basically creating new array and assigning it to variable.
I have a class that needs to write to a file to interface with some legacy C++ application.
Since it will be instantiated several times in a concurrent manner,
it is a good idea to give the file an unique name.
I could use System.currentTimemili or hashcode, but there exists the possibility of collisions.
Another solution is to put a var field inside a companion object.
As an example, the code below shows one such class with the last solution, but I am not sure it is the best way to do it (at least it seems thread-safe):
case class Test(id:Int, data: Seq[Double]) {
//several methods writing files...
}
object Test {
var counter = 0
def new_Test(data: Seq[Double]) = {
counter += 1
new Test(counter, data)
}
}
Did you try this :
def uuid = java.util.UUID.randomUUID.toString
See UUID javadoc, and also How unique is UUID? for a discussion of uniqueness guarantee.
it is a good idea to give the file an unique name
Since all you want is a file, not id, the best solution is to create a file with unique name, not a class with unique id.
You could use File.createTempFile:
val uniqFile = File.createTempFile("myFile", ".txt", "/home/user/my_dir")
Vladimir Matveev mentioned that there is a better solution in Java 7 and later - Paths.createTempFile:
val uniqPath = Paths.createTempFile(Paths.get("/home/user/my_dir"), "myFile", ".txt"),