How to declare a instance name for different classes in Swift - swift

I have two classes which have the same variables and the same methods but the methods do different things. I want to declare an instance name and later on I want to decide which of the classes will be instanciated.
class A {
var x : Int = 0
func calc() {
x = 10
}
}
class B {
var x : Int = 0
func calc() {
x = 33
}
}
class X : UIViewController {
var value : Int = 0
var AorB : (class A or B, I decide later on in the code)
...
override func viewDidLoad() {
super.viewDidLoad()
// Here I want to decide that aorB is an Instance of A or of B
}
How can I solve this?

Try this method:
protocol SomeProtocol{}
class A:SomeProtocol {
var x : Int = 0
func calc() {
x = 10
}
}
class B:SomeProtocol {
var x : Int = 0
func calc() {
x = 33
}
}
class X : UIViewController {
var value : Int = 0
var AorB : SomeProtocol!
...
override func viewDidLoad() {
super.viewDidLoad()
AorB = A()
AorB = B()
// Here I want to decide that aorB is an Instance of A or of B
}

Related

2 instances of 1 class don't share their property

I have 2 classes(A,B) that have instances of another class(C) as their property. Class C have property with some values(no matter what type). A class have methods that removes and append objects from/to C. B class have method that returns objects from class C. Now classes A and B have their views, on A view user able to append and remove object from C and view updates everytime when C changes, and view B call B class method when appear to load object from C, but method returns 0 objects.Here is code example:
class C{
var property = [Something]
}
class A{
var c = C()
func appendOrremove(){
//... some action
}
}
class B{
var c = C()
func getProperty()->[Something]{
//... return property of c
}
}
I can provide exact my code where I faced the problem, but it will much more code than above.Thanks in advance!
Okey I better show my code
class FavoriteBeers{
var favoriteBeers = [Beer]()
}
class BeersListInteractor:BeersListInteractorProtocol{
private var favoriteBeers = FavoriteBeers()
func addToFavorites(beer: Beer){
favoriteBeers.favoriteBeers.append(beer)
saveFavoriteBeers()
}
func removeFromFavorites(_ beer: Beer) {
favoriteBeers.favoriteBeers.removeAll { $0 == beer }
saveFavoriteBeers()
}
}
class FavoriteBeersInteractor:FavoriteBeersInteractorProtocol{
private var favoriteBeers = FavoriteBeers()
func getFavoriteBeers()-> [Beer]{
return favoriteBeers.favoriteBeers
}
}
You don't show how objects of the A and B classes are related but that will be important for how they share the c object. Here's a playground example that would work if something else controls A and B instances.
class Something{
}
class C{
var property = [Something()]
}
class A{
var c: C?
func appendOrremove(){
}
}
class B{
var c: C?
func getProperty()->[Something]{
return c?.property ?? []
}
}
let exC = C()
let exA = A()
exA.c = exC
let exB = B()
exB.c = exC
Another common situation would have A objects create B objects. In that case you might want classes defined something like:
class A{
var c = C()
var b: B
init() {
b = B(c)
}
func appendOrremove(){
}
}
class B{
var c: C
init(_ inC: C) {
c = inC
}
func getProperty()->[Something]{
return c.property
}
}

Can a base class extension capture and return specific implementation?

Suppose we have:
class BaseClass {
var id: String
}
class Child1: BaseClass {}
class Child2: BaseClass {}
struct Structure<T : BaseClass> {
var map = [String: T]()
}
Is it possible for an extension to return the specific type?
extension BaseClass {
static func <- <T : BaseClass>(left: T, right: T) -> Structure<T> where T == Self {
return Structure(map: [left.id, right])
}
}
The compiler doesn't like T == Self, or the left/right operator being T, but you can see what I'm trying to do. I'm trying to return the specific type of BaseClass so that I only have to implement these operators once.
So then you could use it like this:
var child1 = Child1()
var child11 = Child1()
// the structure returned matches the type of the operator inputs
var structure: Structure<Child1> = child1 + child11
If I try to put T in the operator left, right params, the compiler doesn't like that either.
This also doesn't work (for obvious reasons), but if there a way I could rewrite it to make it work?
extension BaseClass {
func combine<T : BaseClass>(with: T) -> Structure<T> {
// this doesn't work because 'self' can be assumed to be T
return Structure<T>(map: [self.id : with])
}
}
You can define the operator. You just can't put it inside of a type.
func + <T>(left: T, right: T) -> Structure<T> {
.init(map: [left.id: right])
}
var structure = Child1() + Child1()
If you want it to be a method, you'll need a protocol.
protocol BaseClassProtocol: BaseClass { }
extension BaseClassProtocol {
func combine(with instance: Self) -> Structure<Self> {
.init(map: [id: instance])
}
}
extension BaseClass: BaseClassProtocol { }
…but if you're going to have a protocol, you can throw the operator in there too if you want.
extension BaseClassProtocol {
static func + (left: Self, right: Self) -> Structure<Self> {
.init(map: [left.id: right])
}
func combine(with instance: Self) -> Structure<Self> {
self + instance
}
}

Override property in Swift 3

I want to override properties in the following class. Say I have a class A that has a boolean property r. For the superclass A, I want r to be set and get normally. For the subclass B, I want r to always be false. I'm not sure why this is harder than it should be...
class A {
init(r: Bool) {
self.r = r
}
var r: Bool {
willSet(n) {
r = n
}
get {
return r
}
}
}
class B: A {
override var r: Bool {
willSet(n) {
r = n
}
get {
return false
}
}
}
let a = A(r: true)
a.r = false
print(a.r) // prints 'false', which is good
let b = B(r: true)
print(b.r) // prints 'true'
b.r = false // ERROR: I can't get pass this point 'Execution was interrupted on playground
print(b.r)
I agree with #Hamish: stored property in base class, with computed property override. Except, a read-only property can't override a mutable property. But, you can make the overridden setter do nothing, and the overridden getter return what you want.
class A {
init(r: Bool) {
self.r = r
}
var r: Bool
}
class B: A {
override var r: Bool {
set {}
get {
return false
}
}
}
let a = A(r: true)
print(a.r) // "true"
a.r = false
print(a.r) // "false"
let b = B(r: true)
print(b.r) // "false"
b.r = true
print(b.r) // "false"

swift: passing by reference

Coming from JS, and trying to pass [JSON] by reference in swift, which is not possible, so I'm trying to wrap it in the object, and made a simple example using a primitive, which still not working, how can i wrap member a, so that changes in referenced object a affect b ? Thanks
class ExampleA {
var a = 0
init(a: Int) {
self.a = a
}
}
class ExampleB {
var a = 0
init(a: Int) {
self.a = a
}
func process(inout p: ExampleA) {
self.a = p.a
print(p.a)
}
}
var a = ExampleA(a: 15)
var b = ExampleB(a: 10)
b.process(&a)
print(b.a) // "15\n"
a.a = 25 // this does nothing to b????
print(b.a) // "15\n"
Your example fails because a is an Int, which is a value type.
When you do the assignment self.a = p.a, you're making a copy of the Int.
To achieve the reference semantics you want, you have to hold reference the ExampleA that's storing the value type. I think you got confused because of your variable naming, confusing the a : Int member of ExampleA with instances of ExampleA named a.
Here's a fix I put together. It gives ExampleB a computed property that transparently accesses the data in ExampleA.
class ExampleA {
var data = 0
init(data: Int) {
self.data = data
}
}
class ExampleB {
var a : ExampleA
var data : Int {
get {
return a.data
}
set {
a.data = newValue
}
}
init(data: Int) {
self.a = ExampleA(data: data)
}
func process(a: ExampleA) {
self.a = a
print(a.data)
}
}
var a = ExampleA(data: 15)
var b = ExampleB(data: 10)
b.process(a: a)
print(b.data) // "15\n"
a.data = 25
print(b.data) // "25\n"
Simple delegation works without any real need for inout or reference semantics:
class ExampleA {
var a = 0
init(a: Int) {
self.a = a
}
}
class ExampleB {
var aObject: ExampleA
init(a: ExampleA) {
self.aObject = a
}
func a() -> Int {
return aObject.a
}
}
var a = ExampleA(a: 15)
var b = ExampleB(a: a)
print(b.a())
a.a = 25
print(b.a())

Extend existing protocols to implement another protocol with default implements

Is it possible to add protocol compliance to a different protocol by way of an extension?
For instance we would like A to comply with B:
protocol A {
var a : UIView {get}
}
protocol B {
var b : UIView {get}
}
I want to give a default implementation (compliance) of B to objects of type A
// This isn't possible
extension A : B {
var b : UIView {
return self.a
}
}
The motivation being to reuse objects of A in cases where a B is required without creating my own "bridge"
class MyClass {
func myFunc(object : A) {
...
...
let view = object.a
... do something with view ...
myFunc(object) // would like to use an 'A' without creating a 'B'
}
func myFunc2(object : B) {
...
...
let view = object.b
... do something with view ...
}
}
As a side note we can extend a class to implement a protocol
class C {
let C : UIView
}
// this will work
extension C : B {
var B : UIView {
return self.c
}
}
and protocols can give default implementations
extension A {
// a default implementation
var a : UIView {
return UIView()
}
}
When extending A, you could specify that the type also conforms to B:
extension A where Self: B {
var b : UIView {
return self.a
}
}
Then make your type conform to A and B, e.g.
struct MyStruct : A, B {
var a : UIView {
return UIView()
}
}
Due to the protocol extension, instances of MyStruct will be able to use a and b, even though only a was implemented in MyStruct:
let obj = MyStruct()
obj.a
obj.b
You can make A inherits from B:
protocol A: B { var a: String { get } }
protocol B { var b: String { get } }
// Default implementation of property b
extension A {
var b: String { get { return "PropertyB" } }
}
class MyClass: A {
var a: String { get { return "PropertyA" } }
func printA(obj: A) {
print(obj.a)
printB(obj)
}
func printB(obj: B) {
print(obj.b)
}
}
let obj = MyClass()
obj.printA(obj)
Since A inherits from B, every property in B is available in A.