Swift 3 introduced the new open keyword that I'm using in a framework.
Does an open class in this framework require an open initialiser to be used outside of said framework, or does the init function inherit the open declaration on the class?
For example:
open class OpenClass {
var A: String
init() { // does this init() function need to be marked open?
A = String()
}
}
Side question: do the variables in the open class OpenClass inherit the open nature of their class?
From SE-0117 Allow distinguishing between public access and public overridability:
Initializers do not participate in open checking; they cannot be declared open, and there are no restrictions on providing an initializer that has the same signature as an initializer in the superclass.
You need not and you cannot declare a init method as open:
open class OpenClass {
open init() { // error: only classes and overridable class members can be declared 'open'; use 'public'
}
}
The default access level for all members of a class (properties
and methods) is internal, that applies to open classes as well.
Related
I have to access to a private method in a Class. I created a library with inside the Class, imported it but it can't still recognize. I have the same problem also with private variables.
Example:
file buffer.dart:
library buflib;
class Buffer{
void _record(){
[...]
}
}
in the same folder: engine.dart
import 'buffer.dart';
class Engine {
Buffer _buff = Buffer()
[...]
void myMethod(){
[...]
this._buff._record();
}
}
I have this error:
The method '_record' isn't defined for the type 'Buffer'.
Try correcting the name to the name of an existing method, or defining >a method named '_record'.dartundefined_method
Any suggestions?
By default, each separate .dart file is a separate library. Since private identifiers are private to the library, they won't be visible to other .dart files.
You can use the library and part of directives to group multiple .dart files into the same library, but those directives aren't documented.
u cant call private methods or variables from out there classes .... u should change it to public by removing "under score"
Should I get the following error:
class.dart:11:11: Error: The getter '_privateID' isn't defined for the class 'Y'.
- 'Y' is from 'class.dart'.
Try correcting the name to the name of an existing getter, or defining a getter or field named '_privateID'.
From the following code?
mixin.dart:
class Mixin {
static int _nextID = 0;
int publicID = _nextID++; // I only need one of these lines
int _privateID = _nextID++; // but this variable is inaccessible
}
class.dart:
import 'mixin.dart';
class X with Mixin {
void run() {
print(publicID); // no error here
}
}
class Y with Mixin {
void run() {
print(_privateID); // Error: _privateID not defined
}
}
void main() {
Y().run();
}
Or is this a bug? If it's not a bug, I'd like to understand why this behavior is reasonable.
When I instead define the mixin in the same file as the above classes, I get no error.
(Dart SDK 2.4.1.)
It is not a bug.
The private field is inherited, but you cannot access it because its name is private to a different library.
Dart's notion of "privacy" is library private names.
The name _privateID in the mixin.dart library introduces a library private name. This name is special in that it can only be written inside the same library.
If someone writes _privateID in a different library, it is a different name, one unique to that library instead.
It is as if private names includes the library URI of the library it is written in, so what you really declare is a name _privateID#mixin.dart.
When you try to read that field in class.dart, you write ._privateID, but because it is in a different library, what you really write is ._privateID#class.dart, a completely different name, and the classs does not have any declarations with that name.
So, if one class needs to access a private member of another class (or mixin, or anything), then the two needs to be declared in the same library, because otherwise they cannot even write the name of that variable.
That is why the code works if you write the mixin in the same library.
If you want to move the mixin to a separate file, but not necessarily a separate library, you can use a part file.
I have been going through the recent swift docs and working out on few examples in understanding private and fileprivate keywords in swift4. I am trying to access a fileprivate and private variable in an extension of the same class and another class subclassing the class but the output is unfruitful. I'm using in the following way
class privateUsageExample: UIViewController {
private var priVar = false
fileprivate var fPriVar = false
}
// usage of extension in the same class
extension privateUsageExample: UITextFieldDelegate {
if priVar{ // do something} // error : expected declaration
if fPriVar{ // do something} // error : expected declaration
func randFunc(){
self. fPriVar = true // accessible don't know the reason
}
}
// access of private and fileprivate variables in another class different file
class anotherUsageInDiffSwiftFile: privateUsageExample {
priVar = false // inaccessible (how to access it)
fPriVar = true // inaccessible (how to access it)
}
can you please help me out in accessing priVar (private) and fPriVar (fileprivate) variable in the extension of the same class in the same file and in another class subclassing the class in the different file.
In Swift 4.0, Private is now accessible in extension but within same file. If you declare/define extension in other file, then your private variable will not be accessible to your extension**
File Private
File-private access restricts the use of an entity to its own defining source file. Use file-private access to hide the implementation details of a specific piece of functionality when those details are used within an entire file.
Syntax: fileprivate <var type> <variable name>
Example: fileprivate class SomeFilePrivateClass {}
Private
Private access restricts the use of an entity to the enclosing declaration, and to extensions of that declaration that are in the same file. Use private access to hide the implementation details of a specific piece of functionality when those details are used only within a single declaration.
Syntax: private <var type> <variable name>
Example: private class SomePrivateClass {}
Here is more detail about all access levels: Swift - Access Levels
Look at this images:
File: ViewController.swift
Here extension and view controller both are in same file, hence private variable testPrivateAccessLevel is accessible in extension
File: TestFile.swift
Here extension and view controller both are in different files, hence private variable testPrivateAccessLevel is not accessible in extension.
Here class ViewController2 is a subclass of ViewController and both are in same file. Here private variable testPrivateAccessLevel is not accessible in Subclass but fileprivate is accessible in subclass.
TLDR: It is now not possible to define a property/function private or fileprivate for a class and then access it from an extension for that class in a different file. Access level private defined properties/functions are accessible in all classes and extensions defined in the same class, but not a subclass. Access level fileprivate defined properties/functions are accessible to extensions of class, subclasses of that class.
You can not write if stubs inside an extension straightaway. It is meant to be written inside a function. So, that is not an issue with private/fileprivate but rather your understanding of extensions. Think of extensions as part of class declaration. In a class as well you can only write if stubs inside a func or closure.
The fileprivate variable inside an extension, was accessible even in Swift 3. So I don't understand, your comment //accessible don't know the reason. Though, in Swift 4, private has changed its meaning in a sense that if the extension is defined at the same file as class, then the private vars are also accessible inside the extensions. This was not true in Swift3.
extension privateUsageExample: UITextFieldDelegate {
func randFunc(){
self.fPriVar = true
self.priVar = false
}
}
If a variable is defined as private/fileprivate I am afraid you can not access them in an extension in another file.
I am working on a private pod and currently I have some difficulty using Typhoon to inject property into the bootstrap class.
My class:
public class MyLibrary: NSObject {
var dependency: MyDependencyProtocol?
}
My assembly:
open class MyLibraryAssembly: TyphoonAssembly {
open dynamic func lib() -> Any
{
return TyphoonDefinition.withClass(MyLibrary.self) { (definition) in
definition?.injectProperty(#selector(getter: MyLibrary.dependency), with: self.dependency())
definition?.scope = .singleton
}
}
}
However, the consumer app will use var lib = MyLibrary() to initialise the object rather than using dependency injection. How do I inject dependency into the MyLibrary class when the init is called?
It might be better to define a class method in your MyLibrary class to return a build instance of your MyLibrary class. This method would:
Bootstrap Typhoon
Ask Typhoon for a built & configured instance of your library
Return it to the method caller
Example: MyLibrary.instance() or MyLibrary.instanceWithConfig(someConfig).
Callers of these methods won't care how the object is build behind behind the scenes - just trust that a built & configured instance is returned.
Still the option to assembly an instance of the library manually using the public constructor.
So in Apple documentation:
Any type members added in an extension have the same default access level as type members declared in the original type being extended. If you extend a public or internal type, any new type members you add will have a default access level of internal.
Giving a sub class of UIView extension:
extension UIViewSubClass
{
var helloWorld : String {
get {
return "helloWorld"
}
}
}
This will mark helloWorld as internal, I have no problem, and I cannot see it in my Objective-C based project.
However, if I mark the extension to be public:
public extension UIViewSubClass
{
var helloWorld : String {
get {
return "helloWorld"
}
}
}
Now helloWorld apprears in my Objective-C based code, which means it is marked as public.
However, I don't see Apple mentions this, did it?
I just saw the documentation said a public class will still has implicit internal level.
public class SomePublicClass { // explicitly public class
public var somePublicProperty = 0 // explicitly public class member
var someInternalProperty = 0 // implicitly internal class member
private func somePrivateMethod() {} // explicitly private class member
}
Marking public for extension seems have different effect than marking a Class definition. This makes me confused.
Could someone help me, is this supposed to be so, or this is a sort of swift bug? I am with swift 2.1 and Xcode 7.2
Answer: Yes, placing access level modifiers (in your case, public, specifically) in front of extensions modify the default access level of all new types in the scope of that extension.
Note that the modifier does not affect the access level of the class/struct/etc being extended (only it's members. However, there are things that ought to be considered, as I will discuss below.
In this discussion, I'll post a few important facts regarding regarding access levels in Swift. All these are from the Swift Language Guide - Access Control - Access Levels.
Let's first assure what you've already stated:
All entities in your code (with a few specific exceptions, as
described later in this chapter) have a default access level of
internal if you do not specify an explicit access level yourself.
OK, this goes in line with what you've quoted in you question: any new type members, whether in a class or structure definition, will have a default access level of internal.
Now, lets look at the access level modifier that you can add in front of extensions:
You can extend a class, structure, or enumeration in any access
context in which the class, structure, or enumeration is available.
Any type members added in an extension have the same default access
level as type members declared in the original type being extended. If
you extend a public or internal type, any new type members you add
will have a default access level of internal. If you extend a private
type, any new type members you add will have a default access level of
private.
Alternatively, you can mark an extension with an explicit access level
modifier (for example, private extension) to set a new default access
level for all members defined within the extension. This new default
can still be overridden within the extension for individual type
members.
This sorts things out. We look at your example, and assume that your class UIViewSubClass has access level public (or compile time error, se below):
/* no access level modifier: default access level will be 'internal' */
extension UIViewSubClass
{
// default access level used: internal
var helloWorld : String {
get {
return "helloWorld"
}
}
}
// modify default access level to public
public extension UIViewSubClass
{
// default access level used: public
var helloWorld : String {
get {
return "helloWorld"
}
}
}
With the discussion above in mind, it's expected that your helloWorld in you public extension ... is marked as internal, as this is, in this context, the default access level. In the context of extensions, access level modifiers work differently than when applied to types.
Finally, we should point out that using a public access modifier when extending a non-public class will yield a compile time error in Swift. So in your case above:
If UISubViewClass is an internal or a private class, then the public extension ... on the class will yield an compile time error.
If UISubViewClass is a public class, then adding the public extension will be redundant as the default access modifier of a public class is already, by definition, public.
I'd say that the error described above is not really an error to avoid runtime errors, but rather to avoid redundant (and confusing) code: public member types or private or internal classes will never make use of itspublic` access level.
class MyImplicitlyInternalClass {
private var myExplicitlyPrivateVar = 0
var myImplicitlyInternalVar = 0
public var myExplicitlyPublicVar = 0 // warning, see (Note 1) below
// redundant 'public': can never be accessed publicly
// myExplicitlyPublicVar will behave as 'internal'
}
public extension MyImplicitlyInternalClass { // error, see (Note 2)
var myNewVarIsInternal : Int { get { return 0 } }
}
/* (Note 1) Compile type warning:
"Declaring a public var for an internal class."
(Note 2) Compile time error:
"Extension of internal class cannot be declared public."
Summary: in theory, these two above are the same type of
'faults', but only the latter is flagged as and error. */
Hence, it only ever makes sense to use the access level modifiers on extensions to make the default access level more restrictive, i.e., using internal extension ... of a public class, or private extension or an internal class.