In swift, what is best practice for having several functions common to more than one class, where inheritance between those classes isn't feasible?
I'm new to programming so please don't condescend. Its just when I first started learning a few months ago I was told its terrible practice to repeat code, and at the time I was coding in Ruby where I could create a module in which all the functions resided, and then just include module in any class where I wanted to use those functions. As long as all variables in the module's functions were declared in the classes the code worked.
Is there a similar practice in swift, or should I be doing something else like making a bunch of global functions and passing the instance variables to those functions? Please be as specific as possible as I'm gonna follow your advice for all code I write in swift going forward, thanks!
simple answer to your question is protocol
define protocol
protocol ProtocolName {
/* common functions */
func echoTestString()
}
extension ProtocolName {
/* default implementation */
func echoTestString() {
print("default string")
}
}
class conforming to protocol with default implementation
class ClassName: ProtocolName {
}
ClassName().echoTestString() // default string
class conforming to protocol with overriden implementation
class AnotherClass: ProtocolName {
func echoTestString() {
print("my string")
}
}
AnotherClass().echoTestString() // my string
While an opinion, I think this is the right route - use a Framework target. Protocols work too. But with a Framework, you can:
Share across projects
Keep everything local in scope what you need or not
Be agnostic in many ways
If you want to use the "include" Swift verb (and all that comes with it), you pretty much need to use a Framework target. If you want complete splitting of code too. Protocols are used when you are within a single project, do not want to "repeat" code pieces, and know you will always be local.
If what you want is to (a) use protocols across projects, (b) include true separate code, (c) have global functions, while (d) passing instance variables... consider a separate target.
EDIT: Looking at your question title ("using same functions") and thinking about OOP versus functional programming, I thought I'd add something that doesn't change my solution but enhances it - functional programming means you can "pass" a function as a parameter. I don't think that's what you were saying, but it's another piece of being Swifty in your coding.
Related
I've just learned about extensions and I was wondering, there was an example about extending a protocol. For example, let's say we have the protocol:
protocol CanFly {
func canFly()
}
which allows all the classes who can fly to basiclly to fly. Now lets say that we use extension to extend the protocol, and we do:
extension CanFly {
func canEat() {
print("I can eat")
}
}
What is the purpose of that if we can just add that func canEat to our protocol? More of those protocols are like an abstract struct so why would we add a func with a body to it?
just wanna say if I've made a mess im sorry for that lol, just want to clear out few things about extension <3
Per Swift documentation on Protocol Extensions:
Protocols can be extended to provide method, initializer, subscript,
and computed property implementations to conforming types. This allows
you to define behavior on protocols themselves, rather than in each
type’s individual conformance or in a global function.
This means you can run logic within the protocol extension function so you don't have to do it in each class that conforms to the protocol.
Personally, I also find extensions useful to extend the functionality of built-in classes like String or UIViewController since extensions can be called from anywhere in an app. I have some open-source extension snippets you can take a look at if you'd like.
Extending a protocol is just one of the possible use cases for extensions, really powerful and useful, but might be confusing at the start.
I suggest you looking through this article, as it dives deeper into more mundane, so to speak, ways to use it.
I'm using a singleton in a Swift 3project I've built.
As part of the project I have registration and login view controllers and I figured I might want registration/login in future projects. So for code reuse I thought about having the registration and login functions in separate .swfit classes and then I'd instantiate these classes in the singleton.
Or just have the registration/login functions as static functions in separate files.
I just wasn't sure if that breaks the idea of a singleton and that all the registration/login functions should be in the singleton.
It's a bit hard to come by practical examples of design patterns in my college degree studies, teachers like data structures, and many other coding topics but not so much about design patterns and how to write better structured code.
In general, you should regard view controllers as not reusable, because they mediate between this particular data and this particular interface (model-view).
But if you can isolate this particular functionality into an independent object, that would make it reusable. What I usually do is make a custom struct and have the view controller own this as a helper object. I don't quite see the point of the putting the struct declaration in a separate file, since it's easy to copy and paste, but you can certainly do that if you like.
(Nor do I see what any of this has to do with Singleton.)
For better learning Design Pattern I recommend the fun and easy reading Head First Design Patterns
Regarding your question about a Singleton pattern in Swift code is always best learned with an example:
final class AccountUtility {
//here is object instantiation to meet the Singleton Design Pattern single instance requirement
static let shared = AccountUtility()
//a private constructor ensures no one can create an instance of this class
private init() {
}
func login() {
}
func register() {
}
}
To use this Singleton Swift class:
AccountUtility.shared.login()
I was reading through another SO question, Swift do-try-catch syntax. In his answer, rickster creates an extension for the OP's custom class. Konrad77 comments that it's a "Really nice way to keep your code clean." I respect their knowledge which leads me to believe I'm missing the point somewhere in my own code.
Are there any other benefits (aside from cleanliness) or reasons to create an extension for a class I created? I can just put the same functionality directly into the class. And does the answer change if I am the only one using the class or if someone else will be accessing it?
In the case of a class that you create from scratch extensions are a powerful type of documentation through structure. You put the core of your class in the initial definition and then add on extensions to provide additional features. For example, adding adherence to a protocol. It provides locality to the contained code:
struct Foo {
let age: Int
}
extension Foo: CustomStringConvertible {
var description:String { return "age: \(age)" }
}
Could I have put the protocol and computed property in the struct declaration? Absolutely but when you have more than one or two properties it starts to get messy and difficult to read. It's easier to create bugs if the code isn't clean and readable. Using extensions is a great way to stave off the difficulties that come with complexity.
Coming from Objective-C, I am very fond of header files which expose the interface of a piece of code. Swift has always bothered me a bit because even the most organized code still tends to bury the public/private API's among the rest of the code, making you dig for details.
Are there any practices or tricks where I can define the public interface of a class or module external to the implementation? Right now I'm just making comments at the top of the Swift file and it feels arcane.
As far as I know you can not just declare a method in a class and implement it at other places in Swift.
I feel you want that for clarity and organizing your methods into class. To achieve that in Swift I follow some techniques that I would be happy to share with you:
Organize methods in groups based on access i.e. public, private and internal. Public methods on top as you want your client to look at them first, then internal and last private.
You may sub organize related methods together for making it easy to understand, maintain and navigate through.
Some time it is good to break above rules to group public and private method if they are related and has heavy dependancies.
You may group related methods that do a specific task in to extensions. I generally follow this pattern for implementing specific protocol or delegate in a class. This you could do in a separate file as well.
This is not direct answer to your question but I have tried to address the core of it by targeting organization of methods in a class.
So I've been exploring the options here and it looks like you can define an interface using a protocol, and having your class conform to that protocol. Kind of out of the way, but if a public interface is the goal, this achieves that.
// Foo.swift
protocol PublicFoo {
func publiclyExposedMethod(arg:AnyObject) -> AnyObject
var publiclyExposedVariable:AnyObject
}
class Foo : PublicFoo {
var publiclyExposedVariable:AnyObject = // something
func publiclyExposedMethod(arg:AnyObject) -> AnyObject {
// do stuff...
}
}
This question already has answers here:
Closed 13 years ago.
Extension methods are really interesting for what they do, but I don't feel 100% confortable with the idea of creating a "class member" outside the class.
I prefer to avoid this practice as much as I can, but sometimes it looks better to use extension methods.
Which situations you think are good practices of usage for this feature?
I think that best place for extension methods is "helper" methods or "shortcuts" that make existing API easier and cleanier by providing default values to arguments of existing methods or hiding repeating chains of method calls.
Contrary to the common beliefs that you can "extend" classes for which you do not have access to the source code, you cannot. You have no access to private methods and objects, all you can do is to polish public API and bend it to your likings (not recommended).
They're great for interfaces (where you can add "composite" behaviour which only uses existing methods on the interface) - LINQ to Objects is the prime example of this.
They're also useful for creating fluent interfaces without impacting on the types that are being used. My favourite example is probably inappropriate for production code, but handy for unit tests:
DateTime birthday = 19.June(1976) + 8.Hours();
Basically anywhere that you don't want to or can't add behaviour to the type itself, but you want to make it easier to use the type, extension methods are worth considering. If you find yourself writing a bunch of static methods to do with a particular type, think about whether extension methods wouldn't make the calls to those methods look nicer.
When the class is not extensible and you don't have control over the source code. Or if it is extensible, but you prefere to be able to use the existing type instead of your own type. I would only do the latter if the extension doesn't change the character of the class, but merely supplies (IMO) missing functionality.
In my opinion, extension methods are useful to enhance the readability and thus maintainability of code. They seem to be be best on entities where either you have no access to the original class, or where the method breaks "Single Responsibility Principle" of the original class. An example of the latter we have here is DSLs. The DSL models are extended with extension methods are used to make T4 templating easier but no methods are added the model unless they are specifically related to the model.
The ideal use for them is when you have an interface that will be implemented in many places, so you don't want to put a huge burden on implementors, but you want the interface to be convenient to use from the caller's perspective as well.
So you put the "helpers" into a set of extension methods, leaving the interface itself nice and lean.
interface IZoomable
{
double ZoomLevel { get; set; }
}
public static void SetDefaultZoom(this IZoomable z)
{
z.ZoomLevel = 100;
}
Extension methods are a great way to add functionality to classes that you don't own (no source), are in the framework or that you don't want to inherit for whatever reason.
I like them, but you are right. They should be used judiciously.