Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's the correct way of thinking C# protected accessor in swift?

In c# we have the protected accessor which allows class members to be visible on inherited clases but not for the rest.

In Swift this doesn't exist so I wonder what's a correct approach for something like this:

I want to have a variable (internal behavior) and and a public method using this variable on a base class. This variable will be used also on inherited clases.

Options I see

  • Forget about base class and implement variable and methods everywhere I need it. WRONG, duplicated code
  • Implement inheritance by composition. I'd create a class containing common methods and this will be used by composition instead of inheritance. LESS WRONG but still repeating code that could be avoided with inheritance
  • Implement inheritance and make variable internal on base class. WRONG since exposes things without any justification except allowing visibility on inherited clases.

Implementation Details for Base Class

I want to have a NSOperationQueue instance and and a public method to cancel queued operations. I add new operations to this queue from inherited classes.

like image 840
StackOverflower Avatar asked Oct 19 '22 23:10

StackOverflower


1 Answers

In Swift the correct answer is almost always protocols and extensions. It is almost never inheritance. Sometimes Cocoa stands in our way, because there are classes in Cocoa more often than protocols, but the goal is almost always protocols and extensions. Subclassing is our last choice.

Your particular case is confusing because NSOperationQueue already has a public method to cancel queued operations (cancelAllOperations). If you want to protect the queue from outside access (prevent callers from using addOperation directly for instance), then you should put the queue inside another type (i.e. composition), and forward what you want to the queue. More details on the specific problem you're solving would allow us to help suggest other Swift-like solutions.

If in the end you need something that looks like protected or friend, the correct solution is private. Put your subclass or your friend in the same file with the target, and mark the private thing private. Alternately, put the things that need to work together in a framework, and mark the attribute internal. The Swift Blog provides a good explanation of why this is an intentional choice.

like image 61
Rob Napier Avatar answered Oct 21 '22 22:10

Rob Napier