Having a Set of a specific interface in java is very useful:
HashSet<MyInterface> mySet;
Is it possible to do something similar in Swift?
I tried unsuccessfully the following:
public protocol DialogDelegate : class, Hashable
{
func myFunction()
}
public final class DialogManager: NSObject
{
private var _dialogDelegates: Set<DialogDelegate>
private override init()
{
_dialogDelegates = Set<DialogDelegate>()
super.init();
}
}
I get the compiler error:
Protocol 'DialogDelegate' can only be used as a generic constraint
because it has Self or associated type requirements
The problem you're having is explained in: What does "Protocol ... can only be used as a generic constraint because it has Self or associated type requirements" mean?
To solve this you could use DialogDelegate as a generic type constraint:
public final class DialogManager<T: DialogDelegate>: NSObject {
private var _dialogDelegates: Set<T>
private override init()
{
_dialogDelegates = Set<T>()
super.init();
}
}
Bear in mind, this won't allow you allowed to mix the types of objects stored in _dialogDelegates; that may or may not be a problem for you.
Related
So I'm new to iOS development and have been working on minor changes to an app at my internship that has a relatively large objective-c code base. I've been learning swift from Treehouse(Wow, love them!) and I just learned about protocols. Currently, they should be used in certain instances and the instructor used this example.
Say you have a company with two different types of employees: Salary and Hourly(Pretty common). Now, they both would inherit from a super class called Employee and both would have to call a function called "pay" which would pay the employee. How do you enforce these classes to implement that function? Sure, use a protocol but that would require you to remember to add that to the function declaration. Is there a way to just add the protocol to the super class "Employee" and then whatever inherits from that class would have to follow that protocol that's part of that superclass. Is there another way to do this? Thanks!
What you are looking for is an abstract class. The purpose of an abstract class is to behave as a base class for concrete classes to inherit from, but an abstract class cannot be instantiated directly.
If Employee was an an abstract class then any attempt to actually instantiate an instance of Employee would be reported as an error by the compiler. You would need to instantiate a concrete subclass of Employee, such as SalariedEmployee or HourlyEmployee.
The definition of the Employee class would include that the calculatePay method was required and again a compile time error would occur if a concrete subclass did not implement that method.
Now, the bad news. Neither Objective-C nor Swift supports abstract classes.
You can provide a similar kind of class by providing an implementation of a method that throws an exception if it isn't overridden by a subclass. This gives a runtime error rather than a compile time error.
e.g.
class Employee {
var givenName: String
var surname: String
...
init(givenName: String, surname: String) {
self.givenName = givenName
self.surname = surname
}
func calculatePay() -> Float {
fatalError("Subclasses must override calculatePay")
}
}
class SalariedEmployee: Employee {
var salary: Float
init(givenName: String, surname: String, annualSalary: Float) {
salary = annualSalary
super.init(givenName: givenName, surname: surname)
}
override func calculatePay() -> Float {
return salary/12 // Note: No call to super.calculatePay
}
}
Whether the calculatePay is part of the base class or assigned to the base class through an extension that adds conformance to a protocol, the result is the same;
The Employee class will need a default implementation of the function that generates some sort of error
Failure of a subclass to implement the method will not cause a compile time error
You could assign a protocol, say, Payable to each subclass individually, but then as the protocol was not part of the base class, you couldn't say something like:
var employees[Employee]
for e in employees {
let pay = e.calculatePay()
}
You would have to use the slightly more complicated:
for e in employees {
if e is Payable {
let pay = e.calculatePay()
}
}
Unfortunately abstract functions are not yet supported. A possible workaround is to launch a fatalError when such function is not overridden by a subclass, doing so:
protocol YourProtocol {
func pay()
}
class Employee: YourProtocol {
func pay() {
fatalError("Must Override")
}
}
class SubEmployee: Employee {
func pay() {
print("stuff here")
}
}
My approach to this is to include the delegate as a parameter in the class initializer. See the code below:
protocol ProtocolExample {
func somethingNeedsToHappen()
}
// typical class example with delegate property for the required protocol
class ClassExampleA {
var delegate: ProtocolExample!
init() {
}
func aCriticalMethodWithUpdates() {
delegate.somethingNeedsToHappen()
}
}
// use class example in a view controller. Can easily forget to invoke the delegate and protocol
class MySampleViewControllerA: UIViewController {
var classExampleA : ClassExampleA!
func loadMyData() {
classExampleA = ClassExampleA()
}
}
// an alternative approach for the class is to include the delegate parameter in the initializer.
class ClassExampleB {
var delegate: ProtocolExample!
init(delegateForUpdates: ProtocolExample) {
delegate = delegateForUpdates
}
func doSomething() {
delegate.somethingNeedsToHappen()
}
}
// go to use it and you're reminded that the parameter is required...
class MySampleViewControllerB: UIViewController {
var classExampleB: ClassExampleB!
func loadMyData() {
classExampleB = ClassExampleB() // error: Missing argument for parameter 'delegateForUpdates' in call
}
}
// so to avoid error:
class MySampleViewControllerC: UIViewController {
var classExampleB: ClassExampleB!
func loadMyData() {
classExampleB = ClassExampleB(delegateForUpdates: <#ProtocolExample#>)
}
}
I have one framework ProviderFramework with the following contents:
public class Provider {
public func fun(some: Model) {
}
}
public class Model {
public let id: Int
init(id: Int) {
self.id = id
}
}
and another UserFramework with the following contents:
public protocol ProviderProtocol {
func fun(some: ModelProtocol)
}
public protocol ModelProtocol {
var id: Int {get}
}
What I want is to make the Provider class conform to the ProviderProtocol class. So in a framework that imports both of the previously mentioned frameworks I have this:
extension ProviderFramework.Model: UserFramework.ModelProtocol {}
extension ProviderFramework.Provider: UserFramework.ProviderProtocol {}
Unfortunately, this results in an error for the second conformance.
So, I tried using an associated types and my ProviderProtocol turned into this:
public protocol ProviderProtocol {
associatedtype T: ModelProtocol
func fun(some: T)
}
and the problematic conformance to this:
extension ProviderFramework.Provider: UserFramework.ProviderProtocol {
public typealias T = ProviderFramework.Model
}
Now there aren't any compile errors, but if I want to use the Protocol as a type like this:
class Consumer {
var provider: ProviderProtocol?
}
I again get an error: 'Protocol 'ProviderProtocol' can only be used as a generic constraint because it has Self or associated type requirements'
I would want to be able to do the last thing. Do I have some bug in my code or if not is there some alternative solution for this problem?
Thanks a lot in advance.
According to the second approach, why not use Provider instead of ProviderProtocol? Since you confirmed typealias T as ProviderFramework.Model in the extension of class Provider.
class Consumer {
var provider: Provider?
}
After reading the docs about this I discovered
In Swift, as in Objective-C, protocol conformance is global—it is not possible for a type to conform to a protocol in two different ways within the same program.
So what is the purpose of the private prefix here
private protocol PartyFormViewControllerDelegate: class {
func partyFormViewController(controller: PartyFormViewController, cancelButtonPressed button: UIBarButtonItem)
}
class PartyFormViewController: GenericViewController {
//...
}
In Swift private means: visible within the current source file.
A private Type could conform to a private protocol, look here:
private protocol Animal { }
private class Dog: Animal { }
class Zoo {
private var animals = [Animal]()
var count : Int { return animals.count }
}
Here, Animal and Dog are visible only within the current files. However, they are used by Zoo which has internal visibility and exposes the count of the animals to the whole module.
I want to be able to have the classes which have a static property (field) which is either inherited from the base class or "mixed" from a protocol. And every class should have it's own implementation of that property. Is it possible? Preferably, it to be immutable.
class C1 {
static let stProperty = "my prorepty1"
}
class C2 {
static let stProperty = "my prorepty2"
}
It's possible, but it's really hard to make this useful in Swift. How do you plan to refer to this property? Let's start with a super-simple implementation:
protocol SomeProtocol {
static var prop: String { get }
}
class C1: SomeProtocol {
static let prop = "This is One"
}
Great. So now I want a function that uses this:
func useProp(x: SomeProtocol) -> String {
return x.prop
// 'SomeProtocol' does not have a member named 'prop'
}
That doesn't work. x is an instance, but I want the type.
// Accessing members of protocol type value 'SomeProtocol.Type' is unimplemented
func useProp(x: SomeProtocol.Type) -> String {
return x.prop
}
This is probably how it will work some day given the word "unimplemented." But it doesn't work today.
func useProp(x: SomeProtocol) -> String {
// Accessing members of protocol type value 'SomeProtocol.Type' is unimplemented
return x.dynamicType.prop
}
Same thing.
Today, you really have to hang this on the object itself and not use static or class:
protocol SomeProtocol {
var prop: String { get }
}
class C1: SomeProtocol {
let prop = "This is One"
}
func useProp(x: SomeProtocol) -> String {
return x.prop
}
That's not so terrible in many cases, since the value for the class is probably also the value for any given instance of the class. And it's really all we can do today.
Of course your problem might be that you don't have an instance yet and you need this information to build an instance. That's really hard today and you should probably rethink your design. You'll generally have to use some other pattern like a Builder. See Generic Types Collection for more.
Now you also said:
or "mixed" from a protocol
I wouldn't say "mixed" here. If you really mean this like a Ruby "mixin", there is no such thing in Swift today. Swift folks often refer to this feature as "default implementation," and it's not currently possible (though I do expect it to come eventually). The only thing you can do in the protocol is say that the implementor has to provide this method somehow. You can't provide it for them.
Sure you can do that with a protocol:
protocol SomeProtocol {
static var foo: String { get }
}
class One: SomeProtocol {
class var foo: String {
get {
return "This is One"
}
}
}
Btw I agree with Rob Napier below that this is a bit off a oddball feature. I do think there are probably use-cases for it, but I also think those can be better implemented with other language features
protocol P {
class var stProperty: String { get }
}
class C1 {
class var stProperty: String {
return = "my property1"
}
}
class C2 {
class var stProperty: String {
return = "my property2"
}
}
Usage:
C2.prop //"my property2"
If you try:
C2.prop = "new value" //"cannot assign to the result of this expression"
Hi I'm using generics a lot in my current project. However, I've come across a problem:
I need a generic function foo<T> to be able to take a parameter that conforms to a generic protocol using a specific type.
For example in Java I can do:
public interface Proto<B> {
public void SomeFunction()
}
public class SampleClass {
}
public class Conforms extends Proto<SampleClass> {
#Override
public void SomeFunction () {}
}
public class TestingClass {
public void Requires (Proto<SampleClass> param) {
// I can use param
}
}
How would I do the same Requires() function in Swift?
I know in Swift you use typealias in the protocol for generics. How do I constrain a parameter based on the typealias?
Prototypes don't seem to have generics the way classes and structs do in Swift, but you can have associated types with typealias, which are close.
You can use type constraints to make sure that the object you pass in adopts the Proto with type constraints. To make the Proto you pass into require has the right B, you use where.
Apples documentation on generics has a lot of info.
This blog post is also a good source of info on doing more complicated things with generics.
protocol Proto {
typealias B
func someFunction()
}
class SampleClass {}
class Conforms : Proto {
typealias B = SampleClass
func someFunction() { }
}
class TestingClass {
func requires<T: Proto where T.B == SampleClass>(param: T) {
param.someFunction()
}
}
You can use a where clause to specify multiple requirements for a generic. I think your example translates to this, but it crashes Xcode. Beta!
protocol Proto {
func someFunction()
}
class SampleClass {
}
class Conforms: SampleClass, Proto {
func someFunction() {
}
}
class TestingClass {
func requires<T: SampleClass >(param: T) where T: Proto {
param.someFunction() // it's this line that kills Xcode
}
}
let testingClass = TestingClass()
let conforms = Conforms()
testingClass.requires(conforms)