Short version:
Assuming I have an app called MyApp. In some situation I have a duplicate class name so that one is MyClass where the other is MyApp.MyClass. How can I call MyApp.MyClass having MyApp constant (do not need to change the code if I change the app name).
Why and what happened (long version):
So assume we are in this MyApp application having following code (the real one is way way longer and used allover the app):
class MyClass {
}
class SomeOtherClass {
class MyClass {
}
func findMyClass(fromMyClass: MyApp.MyClass) -> MyClass {
...
}
}
Because there are two classes called MyClass in inner scope we need to call MyApp.MyClass to get the outer one which is all good.
But it seems a bit silly when MyApp changes which is my case.
Why did it change? I actually added a new target by duplicating the original one because I wanted to have some extra and some different settings (pretty standard procedure). So I renamed the new one to have MyApp-dev where I then got an error Use of undeclared type 'MyApp'.
So is there a keyword that can replace MyApp?
My current solution is to define a typealias on file scope that is then used inside the class to replace MyApp. The problem is that the method is not private so the typealias may not be private either which means I just have an extra name defined globally in the project.
EDIT:
Also there is a setting in Xcode build settings called Product Module Name which may be overridden to explicit naming which fixes the issue. Still this not really a good general solution; I can see cases where you might reuse the same code in multiple modules (creating libraries) which has the same issue. This would still meant that code would need to be fixed for each of these modules.
Related
What does the override do here? After deleting override, I can still compile the program.
abstract class Animal {
def name: String
}
class Cat extends Pet {
override def name: String = "Cat"
}
Adapted from Tour of Scala: Upper Type Bounds:
https://docs.scala-lang.org/tour/upper-type-bounds.html
You are right, this is a particular case where removing it does not affect the program. Why override is allowed here is for various flexibility reasons:
say you want to add an implementation in the parent class Animal - that would work without affecting the behavior of Cat because you used the prophylactic
override in Cat to prevent that idea from affecting your extended class. So the subclass becomes just a little bit less tightly-coupled from your base class in this case.
say someone else deletes the abstract method name or renames it in the parent class (without knowing that method is being overridden). This would raise compile errors in all classes that overridden it, to he/she will know that this change should be thoroughly thought before being done, as it will affect the interface and the way clients interact with your code.
also it makes the compiler help you catch typos in subclasses: say you created another subclass and add a different method but misspell name for something else, say nme - you'll see that if you used override the compiler will warn you that nme does not override anything in the base class. (Thanks compiler!)
for me personally, using override in subclasses acts as a marker so I know that this method is also defined in the base class, without having to manually check the base class, which usually resides in a different file.
So it's more of a "best practice" thing rather than a necessity in this case, and everyone is free to use it as they see fit.
I already read the documentation about the new modifiers "open" and "fileprivate". But there are two things that I don't understand:
Why is it not possible to declare protocols or extensions also as "open"? And does it mean that it's not possible to use these things outside a module?
If I don't want to build my classes for a module but an common app, should I declare my classes and methods as "open" anyway or is it good practice to keep them only "public"?
As this answer says:
An open class is accessible and subclassable outside of the defining module. An open class member is accessible and overridable outside of the defining module.
A public class is accessible but not subclassable outside of the defining module. A public class member is accessible but not overridable outside of the defining module.
I think the answer to your first question, is that you can't override or subclass a protocol or extension. Thus, there is no use for such things to be open because public already makes them accessible outside of a module.
For your second question, I would say that you should only declare your own classes as open if you plan on overriding or subclassing. Otherwise you are allowing unnecessary access to these items. Most of the time public should suit your needs.
Edit:
As #Alex points out, I don't think there are many downsides to allowing this "extra access". The only thing I can think of is if you just wanted to protect your classes from your future self, but that may or may not be applicable. Thus, if this is not the case, there shouldn't be much harm in setting them as open by default.
open is for another module, for example in we use it in unit test or in cocoa pods, you can inherit from a pod (if it's: open class somePod {...}) or override some function (if it's: open func someFunctionInPod{...}) in your project.
In my Swift code, I often use the private modifier to limit the visibility of helper classes. For example, in one file, I'll have a GridController and a GridControllerModel.
The GridController (the UI) should be accessible to the rest of the application, but the model class is wholly internal and should never be accessed by the rest of the application.
I can address this in Swift by making both classes private and keeping them in the same file. But this gets unwieldy as classes get bigger. What I'd like to do is keep each class in a separate file (for programming convenience), but prevent access to the model class anything but GridController (for information hiding purposes).
Is there any way to do this in Swift?
As others have said, there is no way to do exactly what you want today in Swift.
One alternative is to use an extension in another file to add GridControllerModel as a nested subtype of GridController. e.g.
//GridControllerModel.swift
extension GridController {
struct GridControllerModel {
let propertyOne:String
let propertyTwo:String
}
}
This allows your GridController class in its own separate file to declare something like:
var model = GridControllerModel()
However, the rest of the application can still access the GridControllerModel type like this:
//SomeOtherClass.swift
var nested = GridController.GridControllerModel()
So, you do achieve some separation by making the model type a subtype of GridController, but it isn't true access control. On the plus side, it will not appear in code completion outside of the GridController class as "GridControllerModel", you would need to first type "GridController" and then "." to see the subtype "GridController.GridControllerModel"
It's also worth noting that an additional access control level is currently under review and likely to be in the next version of Swift (3.0) :
https://github.com/apple/swift-evolution/blob/master/proposals/0025-scoped-access-level.md
Assuming this proposal is accepted and implemented, you would be able to update your declared subtype like this:
//GridControllerModel.swift
local extension GridController {
struct GridControllerModel {
let propertyOne:String
let propertyTwo:String
}
}
(Note the "local" keyword above now). This would make the GridControllerModel type invisible and inaccessible to all classes except GridController and any extensions of GridController.
So, I would recommend that you consider this nested subtype approach today, because when Swift 3.0 arrives later this year, it's likely to support what you want by simply adding a keyword in front of your subtype declaration. And in the meantime, you get some of the separation you want as well.
No, there isn't an access modifier that restricts visibility to only a certain set of files. But you probably don't need that.
What does exist:
private: restricts visibility to within the same source file.
internal: restricts visibility to within the same module.
If you're building a piece of software that's too big for one source file, but both defines an outward-facing interface and internal details that should stay hidden from clients of that interface... then you're probably working at a level where it's appropriate to build a framework. Your framework can then define features that are internal for its use only and separate from the public interface it exposes to clients.
Is it considered poor technique to create multiple classes in one swift file, or is it best to create a separate swift file for each class?
For example, which is better:
A. Multiple classes in ViewController.swift:
1. alpha.swift:
class alpha: UIViewController { ... }
class beta: UIWebView { ... }
class gamma: UINavigationController { ... }
B. Separate .swift files for each class:
1. In alpha.swift:
class alpha: UIViewController { ... }
2. In beta.swift:
class beta: UIWebView { ... }
3. In gamma.swift:
class gamma: UINavigationController { ... }
Short answer: it depends.
Long answer:
If you have small short classes that are strongly binded together, it's correct to put the in the same file.
If you have long, unrelated classes, then you better put them in different files.
It's not a poor technique, IF the classes are connected.
To decide if they are connected, ask: Can one class be used without the other?
If yes, then you should have two different files, since you might need to use just one of the two.
For example, in C++, collections have an inner class for their iterators. (I know it's a C++ example, but the question isn't really language related).
Though if the classes have nothing to do with each other (being on the same view doesn't count), then they should each have their separate classes.
I have different answer for this question based on painful debugging and searching in the internet for last few days. I'm c++ dev with more than 15 years experience. Coming from this language I'm familiar with few design techniques which needs protected access. Since Swift doesn't support it and as it turns out they won't support it in near future, I've start using private access and write few classes in the same file. That way I've workaround the missing protected modifier (private functions are visible in the same file, so they will be visible for all classes in the same file, and if these classes are derived classes the private is actually working as protected). Well everything is fine and I was happy before found out that my application crashed with EXC_BAD_ACCESS code=1 ... The exceptions was not because of my code, it was because it layout of the members were somehow wrong. For example if i called one function a() from the derived class through instance variable the func b() was called. The b() was also member of the same class and was define before the a(). That is why some functions thrown bad access exception. Instance pointer was corrupt. After I moved all 3 classes to independent files everything looked fine.
Not sure that this was the actual reason or I've done something wrong, but not 100% of cases when you define multiple classes in the same file will be with defined behaviour. May be that is compiler problem, Swift is young language and even that I'm testing with Gold Master studio which is supposed to be stable, there are still a lot of bugs.
A very strange thing indeed. I have the following project structure:
myproject/one/two
Inside package myproject I have a class:
abstract class A (two: Buffer[Int])
and then, inside package one I have:
object B extends A (Buffer[Int](1, 2, 3)) {
val с = two.map(_ + 1) // ERROR
}
However, the erros says:
object map is not a member of package
myproject/one/two
which is obviously erroneous because it should be perfectly clear that I don't refer to the packages here, but to the local variable... And two also is not shown in context-assist after this. in B, but is shown in A (Scala-IDE). Is this an intended behavior and I am doing something wrong or is it a bug?
UPDATE:
(simultaneously suggested by Nicolas :D ) Been able to resolve the name collision by specifying two as val (making it public). I did not notice at first, but it was private and unavailable in the successor class. Nevertheless I am still wondering, why and how did Scala pick up a package instead of saying that the variable does not exist or is not accessible?
It's not as clear as you might think. Without a modifier, two is private to abstract class A class A. Thus your declaration of a is equivalent to abstract class A (private[this] A). It means that field two can't be seen from object B. A direct consequence is that the compiler look into the only defiition of two visible from B: the package two.