48

I want to create a class that inherits from another class, which is in a different file.

For example:

Class1.swift

class Class1
{
    protected var 
    //Do Stuff
}

Class2.swift

class Class2:Class1
{
    //Do stuff
}

How would I be able to have access to a 'protected' variable/function in swift?

When I declare a private variable/function, I can only use it in that class. If I use 'fileprivate', my other class HAS to be in the same file as Class1. What I want to do is keep my classes in separate files and use the Groups from within Xcode to know what class belongs with which category.

magohamote
  • 1,484
  • 1
  • 17
  • 29
iProgram
  • 6,057
  • 9
  • 39
  • 80
  • Possible duplicate of [Does Swift have access modifiers?](http://stackoverflow.com/questions/24003918/does-swift-have-access-modifiers) – Sulthan Jan 20 '17 at 13:55
  • @Sulthan I saw that post becase it did not say anything about 'protected'. This could have been somthing that was added in a later version of swift, or be accsessed in a diffrent way. – iProgram Jan 20 '17 at 13:56
  • A group in Xcode has nothing to do with compilation or with the language itself. It's just a way to logically group files in your project, the same as folders in your file system. If you want to separate implementation, you will have to use *modules*, that is, *targets* in the project. And then use `internal`. – Sulthan Jan 20 '17 at 13:57
  • The post I linked is updated for Swift 3. – Sulthan Jan 20 '17 at 13:57
  • 3
    @I know about the groups. I like having classes in diffrent files so it is easy for me to see where each class etc. would be in the file structure. – iProgram Jan 20 '17 at 13:59

5 Answers5

71

You would have to use internal for that as Swift doesn't offer a protected keyword (unlike many other programming languages). internal is the only access modifier between fileprivate and public:

Internal access enables entities to be used within any source file from their defining module, but not in any source file outside of that module. You typically use internal access when defining an app’s or a framework’s internal structure.

There is a blog post that explains a little bit more about why the language designers chose not to offer a protected keyword (or anything equivalent).

Some of the reasons being that

It doesn’t actually offer any real protection, since a subclass can always expose “protected” API through a new public method or property.

and also the fact that protected would cause problems when it comes to extensions, as it wouldn't be clear whether extensions should also have access to protected properties or not.

Keiwan
  • 8,031
  • 5
  • 36
  • 49
  • Thanks for the answer. I knew there was internal, however since all the code is in one unit, this means that I may as well have it as public. – iProgram Jan 20 '17 at 13:58
  • @iProgram But that's the problem. You have all the code in one unit. – Sulthan Jan 20 '17 at 13:59
  • Thourght that was how apps where ment to be. So when making applications, wverything should be in diffrent units? If so, what is the best way in doing this? Or is that for another subject? While I am not new to development, I am if you know what I mean. – iProgram Jan 20 '17 at 14:01
  • There are several design patterns but the most common is [Model-View-Controller](https://developer.apple.com/library/content/documentation/General/Conceptual/DevPedia-CocoaCore/MVC.html) – Alex S Jan 20 '17 at 17:52
  • "> It doesn’t actually offer any real protection, since a subclass can always expose “protected” API through a new public method or property." The same applies to `internal` keyword as well yet they allow `internal` to be there as default modifier for classes in a package. Also I don't think `protected` is for the sole purpose of "protection", but for the cleanliness of externally visible interface, some methods are just useless to be exposed and will confuse the consumer if they don't understand internally how the class works. but hey, it is apple, being opinionated doesn't surprise me. – Norman Xu Jun 21 '23 at 23:38
7

Even if Swift doesn't provide protected access, still we can achieve similar access by using fileprivate access control.
Only thing we need to keep in mind that we need to declare all the children in same file as parent declared in.

Animal.swift

import Foundation

class Animal {
    fileprivate var protectedVar: Int = 0
}

class Dog: Animal {
    func doSomething() {
        protectedVar = 1
    }
}

OtherFile.swift

let dog = Dog()
dog.doSomething()
D4ttatraya
  • 3,344
  • 1
  • 28
  • 50
  • 24
    The problem is the superclass and the subclass will have to be in the same file. It would be a code design issue. – DEADBEEF Feb 05 '18 at 16:04
  • 1
    There isn't a better answer, though since "inheritance" is an "axis" the designers decided not to employ. The only practical solution is to use file separation for instance variables and intelligently use files to separate that omitted "axis" of access control, the one presented by D4ttatraya. – Aaron Mar 14 '18 at 02:15
5

Use an underscore for such protected variables :/

That's about it ...

class RawDisplayThing {
    
    var _fraction: CGFloat = 0 {
        didSet { ... }
    }


class FlightMap: RawDisplayThing() {

    var currentPosition() {
        ...
        _fraction = 
        ...
    }
}

Everyone has to "just agree" that only the concept class can use the "_" variables and functions.

At least, it's then relatively easy to search globally on each "_" item and ensure it only used by the superclasses.

Alternately, prepend say "local", "display", or possibly the name of the class (or whatever makes sense to your team) to such concepts.

class RawDisplayThing {
    
    var rawDisplayFraction: ...
    var rawDisplayTrigger: ...
    var rawDisplayConvolution: ...

etc etc. Maybe it helps :/

Community
  • 1
  • 1
Fattie
  • 27,874
  • 70
  • 431
  • 719
  • 1
    Don't understand why this language still doesn't offer such a basic feature. Coming from Java/Android, I have to spend hours to find DIY workarounds to make on my own basic C++ like feaures such as protected or abstract classes, while so many other languages just have them already set up (PHP, C#, Java, Kotlin, ..) – Jerem Lachkar Nov 18 '20 at 17:54
  • 1
    (FTR THIS good article https://medium.com/ios-os-x-development/swift-needs-protected-access-level-b966001a1d08 links to, indeed, the exact place in the Swift Guys's Writing where they justify this issue. For me, it's all whack, give me assembler :) ) – Fattie Nov 18 '20 at 18:04
  • 1
    lol, I actually find Java really good at enforcing rules at compile time, coming from UML business models. And a lot of languages just have these C++ like features. The fact that Swift hasn't force me to spend time to revisit my UML business logic which is quite frustrating... – Jerem Lachkar Nov 18 '20 at 18:23
  • For the full Good Apple / Bad Apple experience, have a muck around with CoreData! Oh my .. – Fattie Nov 18 '20 at 18:55
2

If you dont want to have both classes belonging to the same file, here is what you can do:

class Parent {
    internal private(set) var myProtectedBoolean = false
}

Then on the child class:

class Child: Parent {
   private var _myProtectedBoolean: Bool = false;

   override var myProtectedBoolean: Bool {
       get { return _myProtectedBoolean }
       set { _myProtectedBoolean = newValue }
   }
}
0

The next best thing in my opinion would be to have both classes in the same file and use fileprivate instead.

class Class1 {
   fileprivate var foo: String
}

final class Class2: Class1 {
   func bar() {
      // Class1.foo is accessible from Class1 but nothing else
      self.foo = "bar" 
   }
}
Charlton Provatas
  • 2,184
  • 25
  • 18