0

I have two bellow functions with Generics.

func objectFunc<T:SomeProtocol>(obj:T)
func arrayFunc<T:SomeProtocol>(obj:[T]) 

Can I group these functions into one function?

I found the link Checking if an object is a given type in Swift, but this is a little different.


Added.

For example, I want to do like bellow.

func objectAndArrayFunc<T>(arg:T, someEnum:SomeEnum){
  switch someEnum {
    case A:
      // something
    case B:
      // something
  }

  if let items = arg as? [T] {
    for item in items {
      // something
    }
  } else if let item = arg as? T {
      // something
  }
  // I want to do something [T] and T common processing

}
enum SomeEnum {
  case A
  case B
}

Also, SomeEnum count might increase.

Community
  • 1
  • 1
kwmt
  • 134
  • 1
  • 2
  • 9

1 Answers1

0

Generally speaking, depends on what // something is. There are many ways ...

Private common processor

protocol Property {
  var name: String{ get }
}

enum SomeEnum {
  case A, B
}

func process<T:Property>(object:T, someEnum:SomeEnum) {
  process(object, nil, someEnum)
}

func process<T:Property>(objects:[T], someEnum:SomeEnum) {
  process(nil, objects, someEnum)
}

private func process<T:Property>(object: T?, objects:[T]?, someEnum:SomeEnum) {
  switch someEnum {
    case .A:
      // something
      break
    case .B:
      // something
      break
  }

  // holds all items for common processing
  var itemsToProcess: [T] = []

  if let items = objects {
    // process items
    itemsToProcess = items
    for item in items {
      println("\(item.name)")
    }
  } else if let item = object {
    // process single item
    itemsToProcess = [item]
    println("\(item.name)")
  }

  // iterate over single/all items and process them
  for item in itemsToProcess {
    println("\(item.name)")
  }
}

Wrap it to Enum

protocol Property {
  var name: String{ get }
}

enum SomeEnum {
  case A, B
}

enum Objects<T> {
  case Single(T)
  case Multiple([T])
}

private func process<T:Property>(objects: Objects<T>, someEnum:SomeEnum) {
  switch someEnum {
    case .A:
      // something
      break
    case .B:
      // something
      break
  }

  // holds all items for common processing
  var itemsToProcess: [T] = []

  switch objects {
    case .Multiple(let items):
      // process items
      itemsToProcess = items
      for item in items {
        println("\(item.name)")
    }

    case .Single(let item):
      // process single item
      itemsToProcess = [item]
      println("\(item.name)")
  }

  // iterate over single/all items and process them
  for item in itemsToProcess {
    println("\(item.name)")
  }
}

struct Prop: Property {
  var name: String {
    return "hi"
  }
}

let prop = Prop()
process(.Single(prop), .A)
process(.Multiple([prop]), .B)

Unfortunately, the 2nd example segfaults Swift 1.2 compiler.

Anyway, it really depends on what your goal is. Why you do not want pass even single item as [T], ...

To answer your question - no, you can't pass T or [T] in one argument, different types. Unless you wrap it to Enum or whatever, unless you do want to use AnyObject and make as dances, ...

zrzka
  • 20,249
  • 5
  • 47
  • 73