Static methods

Hi,

Overview

I generally follow a convention to use a static method when the method doesn't access any of the instance's properties / instance's functions.

Questions

  1. Is this a good approach to use static methods for this case? A lot of times I see code using normal instance functions even when no instance properties or functions use instance (non-static) methods.
  2. What is a preferred name for below mentioned function? (makeConfiguration() or configuration())

Code:

struct Configuration { }

class Car {
    let name = "hello"
    
    static func makeConfiguration() -> Configuration {
        // some logic that doesn't require any of instance's properties / instance's functions
        return Configuration()
    }
}

Thanks.

1 Like

Your approach is sound. The only downside I can think of is that one has to always qualify with Self or with the associated type's name when accessing the static members from outside of the static functions.

class Car {
    static private (set) var serialNumber = 0
    
    private init () {}
}

extension Car {
    static func create () -> Car? {
        guard serialNumber < 2048 else {
            return nil
        }
        
        let it = Car ()
        serialNumber += 1
        return it
    }
}

extension Car: CustomStringConvertible {
    var description: String {
        "serial number: \(Self.serialNumber)"
    }
}

let car = Car.create()
print (car!)
print (Car.serialNumber)

Thanks @ibex10

My case is just to return a configuration not to return the car in the static method.

I have edited the original question hopefully it is more clear.

1 Like

why can’t this just be part of Configuration.init?

3 Likes

Thanks @taylorswift

That is a fair point, in my real project I am trying to build a URL specific to this Car. It is a private helper function used internally within Car.

class Car {
    let name = "hello"
    
    private static func makeURL() -> URL? {
        // some logic that doesn't require any of instance's properties / instance's functions
        return URL(string: "something here")
    }
}

My broader question is about the role of static methods, I tend to use them when no instance properties / instance methods are being accessed.

In other code bases, generally I see most times that normal instance methods are used even when no instance properties / instance methods are accessed.

So I was wondering if using static methods is preferred to using instance methods for this case (when no instance properties / instance methods are accessed).

1 Like

This is a great question. Although the rules regarding this kind of thing are clear, people don't talk about them, and that makes it very difficult to form mental standards which allow for coding to not take forever.

A static method that returns Self is conceptually an initializer.
The reason you wouldn't use an initializer is because you want to give it a name.
If such an "initializer" takes no arguments, it's a property.
Neither of these have the name of the type at the end of the name.
If you're returning something else, you need the name of the thing, as a suffix. This is conceptually a nested initializer—something for which there exists no language feature, and instead, requires a naming convention. If you don't have a name for the thing before the suffix, put make there. It's rare to not need a name. I.e. why is Car initializing a URL?

As for static vs. instance, consider why you can even have a default property value for a constant.
There's no necessity for the feature, but sometimes it makes conceptual sense.
Is a car making a URL?

2 Likes

that gives me an idea…

extension URL
{
    internal static
    var car:Self? { ... }
}

let url:URL = .car
2 Likes

Thanks @anon9791410

Yes as you suggested it is possible for me to have a static constant with this value. It is a good idea (shown below).

class Car {
    let name = "hello"
    private static let url = {
        // some complex logic
       // this might run into a number of lines
        return URL(string: "something here")
    }()
}

Edited: to make the variable static

Questions:

  1. When one reaches for a static method does it mean there is a design issue and the method would rather be better suited as an instance method in a different class / struct?
  2. Sorry if I keep asking the same question, because I am confused about the role of static functions in class / struct, I don't see many using them but I tend to use them. And hence the question.
1 Like

Thanks @taylorswift

That is also a good idea, I am learning different ways of handling this.

Please bear with me as I am still confused about the role of static methods (as stated in my previous post in the thread).

1 Like

no. but i find it a bit clearer to place it as an extension on URL. you're not exposing it as public API, so you don't need to worry about name collisions or symbol pollution.

2 Likes

Thanks @taylorswift for clarifying this.

It is good to know that static methods do have a role when needed. I guess it also depends on personal preference.

Like you said having an internal initialiser in the extension also is a good option.

Thanks @mgriebling for confirming that, it is good to know the use cases.

I think you meant self(all lowercase)

Self (S is uppercase) refers to the type itself which is used while invoking static methods.

oh my bad I misread your answer. sorry about that

For what it's worth: I sometimes write pure functions that neither reads or mutates self as instance methods, just to avoid the Self. clutter of static functions. I think it would be great if the compiler would resolve foo() to Self.foo() if no other candidate matches. Are there any downsides to that?

3 Likes