1

I want to have a function return a type which I can add a new function, but still can be generally recognized as String (still have all of String's methods and still can be received by any parameter that received String).

But when I try to derive a class from String, I get this error:

Inheritance from non-protocol, non-class type 'String'

Of course, I can instead use an extension to extend the existing String to add that function, but I felt that this will pollute the String with unnecessary and unrelated functions for general use.

For example, functions that I want to add might be like this:

class ImageUrl : String {

    func getImage (callback: ((UIImage?)->Void)) { ... }

}

or like this:

class Base64 : String {

    var image : UIImage { ... }
    var data : Data { ... }
    var string : String { ... }

}

Which will be confusing if I extend these functions to the main String type.

How can I do this in Swift? Or is there any workaround to this? Thanks.

2
  • 2
    String is implemented in Swift as struct. So there is no way of subclassing it. Commented Dec 4, 2018 at 10:06
  • 1
    String is a struct. Structs don't support inheritance. Commented Dec 4, 2018 at 10:06

2 Answers 2

2

You cannot inherit from String in Swift, because it is a struct. You can only add functionality by using an extension as you mentioned, but this will not let you use stored properties (computed properties as you wrote in the question are allowed).

However, a better approach for your need would be to use composition:

class Base64 {

    let str: String

    required init(value: String) {
        self.str = value
    }
}

Here you can add your desired functionality.

Sign up to request clarification or add additional context in comments.

2 Comments

Although Base64 is probably a bad idea. ImageUrl from the question is probably a better example.
Yeah, this is my current approach. It's just sad that these classes cannot immediately conform to parameters that accept String. Thanks!
1

You could create a String extension using the fileprivate modifier to avoid polluting the global namespace. The functions would then only be available to code in the source file rather than the global namespace.

fileprivate extension String {
  var image : UIImage { ... }
  var data : Data { ... }
  var string : String { ... }
}

3 Comments

“fileprivate” restricts access to the same source file, “internal” to the same module.
Ah. I though "module" and "source file" were the same thing. Good to know :).
This extension is meant to be used globally in the project, it's part of the current project. But I just want to make a little differentiation that if I see an ImageUrl type, it's still can conform to String, but you're able to have a little bit extra functions there. Not a big deal, but to know why String can't be derived is enough. Thanks.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.