declare generic class with a generic class as a parameter in swift - swift

I wrote these simple generic classes and it worked great:
class LinkedListNode <T> {
var value: T
var next: LinkedListNode<T>?
weak var prev: LinkedListNode<T>?
init(value: T) {
self.value = value
self.next = nil
}
}
class LinkedList<T> {
var first: LinkedListNode<T>? = nil
var last: LinkedListNode<T>? = nil
var count = 0
#discardableResult func append(_ value: T) -> LinkedListNode<T> {
let new = LinkedListNode(value: value)
new.prev = last
last?.next = new
count += 1
last = new
if first == nil {
first = new
}
return new
}
}
And I used it like:
let list = LinkedList<Int>()
list.append(3)
let lastNode = list.append(5)
Now I realized there are some cases when I need to have a customized node: CustomNode<T>, subclass of LinkedListNode<T>. So I would like to be able to pass the class to be used as the node as:
let list = LinkedList<CustomNode<Int>>()
list.append(3)
let customNode = list.append(5)
How can I declare my class to have it like this or something similar?
I have tried the following declaration but weird errors rise. Is this even possible?
class LinkedList<Node<T>: LinkedListNode<T>> { ...
Update 2019/07/26.
Even with Kamran's approach this method does not compile. I am not sure if this is doable without a protocol. See my comment on Kamran's answer.
func remove(node: LinkedListNode<T>) { // change to `func remove(node: U)`
node.next?.prev = node.prev
node.prev?.next = node.next
if node === first {
first = first?.next
}
if node === last {
last = last?.prev // Error here: "Cannot assign value of LinkedListNode<T>? to U?"
}
}

The syntax you are trying can be achieved as below,
class LinkedListNode <T> {
var value: T
var next: LinkedListNode<T>?
weak var prev: LinkedListNode<T>?
required init(value: T) {
self.value = value
self.next = nil
}
}
class GenericCustomNode<T>: LinkedListNode<T> {
required init(value: T) {
super.init(value: value)
}
}
class NonGenericCustomNode: LinkedListNode<Int> {
required init(value: Int) {
super.init(value: value)
}
}
class LinkedList<T, U: LinkedListNode<T>> {
var first: U? = nil
var last: U? = nil
var count = 0
#discardableResult func append(_ value: T) -> U {
let new = U(value: value)
new.prev = last
last?.next = new
count += 1
last = new
if first == nil {
first = new
}
return new
}
func remove(node: U) {
node.next?.prev = node.prev
node.prev?.next = node.next
if node === first {
first = first?.next as? U
}
if node === last {
last = last?.prev as? U
}
}
}
Usage:
let list = LinkedList<Int, LinkedListNode<Int>>()
list.append(5)
print(list.first?.value)
let someCustom = LinkedList<Int, GenericCustomNode<Int>>()
someCustom.append(15)
print(someCustom.first?.value)
let otherCustom = LinkedList<Int, NonGenericCustomNode>()
otherCustom.append(2)
print(otherCustom.first?.value)
Output:
Optional(5)
Optional(15)
Optional(2)

You will need to define a protocol with an associated type:
protocol Node: class {
associatedtype Value
var value: Value {get set}
var next: Self? {get set}
var prev: Self? {get set}
init(value: Value)
}
final class BasicNode<Value>: Node {
var value: Value
var next: BasicNode<Value>?
weak var prev: BasicNode<Value>?
init(value: Value) {
self.value = value
}
}
final class CustomNode<Value>: Node {
// customize however you want
var value: Value
var next: BasicNode<Value>?
weak var prev: BasicNode<Value>?
init(value: Value) {
self.value = value
}
}
class LinkedList<N: Node> {
var first: N? = nil
var last: N? = nil
var count = 0
#discardableResult
func append(_ value: N.Value) -> N {
let new = N(value: value)
new.prev = last
last?.next = new
count += 1
last = new
if first == nil {
first = new
}
return new
}
}
However, this will require using your basic linked list in an annoying way all the time:
let list = LinkedList<BasicNode<Int>>()
Depending on how you need to customize the node, I would consider finding a way to customize the behavior in the LinkList class itself using dependency injection.

Related

How can I build a recursive function in Swift to return a String?

I have a Node class defined as follows. value: T is a String
class Node<T> {
var value: T
weak var parent: Node?
var children = [Node<T>]()
init(_ value: T) {
self.value = value
}
func add(_ node: Node<T>) {
children.append(node)
node.parent = self
}
}
I'd like to build a function to return a String of the current Node's value and all Parent values. Ideally, the function would be defined in the class. For example,
currentnode.listAllValues()
would return -> "/parent2value/parent1value/currentnodevalue"
So far the following function works with a simple print(), and I've also considered using an inout parameter.
func listAllValues(node: Node<String>) {
print(node.value)
if node.parent?.value != nil {
listAllValues(node: node.parent!)
}
}
You can achieve this with an instance method which calls itself on the parent node first, if there is one:
func listAllValues() -> String {
if let p = parent {
return "\(p.listAllValues())/\(value)"
} else {
return "/\(value)"
}
}
Or as an obfuscated one-liner:
func listAllValues() -> String {
return "\(parent?.listAllValues() ?? "")/\(value)"
}
Example:
let p2 = Node("parent2value")
let p1 = Node("parent1value") ; p2.add(p1)
let n = Node("currentNodeValue") ; p1.add(n)
print(n.listAllValues())
// --> /parent2value/parent1value/currentNodeValue
Here you go:
func desc(_ s:String? = nil) -> String {
var me = String(describing:self.value)
if let prev = s {
me += "/" + prev
}
return self.parent?.desc(me) ?? me
}
Example:
let n = Node("hey")
n.add(Node("ho"))
n.children.first?.add(Node("nonny nonny no"))
let start = n.children.first!.children.first!
print(start.desc())

Swift: send type as argument and compare a variable's type with it

I want to implement a function like this one:
protocol Base {
var value: Int { get set }
}
class ObjectTypeA: Base {
var value: Int = 0
}
class ObjectTypeB: Base {
var value: Int = 1
}
var objects: [Base] = [ObjectTypeA(), ObjectTypeB()]
func updatePropertyForType(type: Base.Type, value: Int) {
objects.filter({ $0 is type }).forEach { // <<< ERROR IS HERE
var object = $0
object.value = value
}
}
updatePropertyForType(ObjectTypeB.self, value: 10)
But there is an error:
'type' is not a type
Please, help me fix it.
See this answer:
protocol Base: AnyObject {
var value: Int { get set }
}
class ObjectTypeA: Base {
var value: Int = 0
}
class ObjectTypeB: Base {
var value: Int = 1
}
var objects: [Base] = [ObjectTypeA(), ObjectTypeB()]
func updatePropertyForType(type: Base.Type, value: Int) {
objects.filter({let item = $0; return type === item.dynamicType }).forEach {
$0.value = value
}
}
call it with:
updatePropertyForType(ObjectTypeA.self, value: 3)
As the other answers have eluded to, you cannot use meta-types with is. However, a nicer solution would be to simply use generics. This will allow Swift to infer the type you pass into the function, allowing you to write it as:
protocol Base : class {
var value: Int { get set }
}
class ObjectTypeA: Base {
var value: Int = 0
}
class ObjectTypeB: Base {
var value: Int = 1
}
var objects: [Base] = [ObjectTypeA(), ObjectTypeB()]
func updateElements<T:Base>(ofType type: T.Type, withValue value: Int) {
objects.filter{ $0 is T }.forEach{ $0.value = value }
}
updateElements(ofType: ObjectTypeB.self, withValue: 10)
You'll also want to make your Base protocol class bound (: class) in order to allow Swift to treat Base typed instances as reference types (allowing you to do $0.value = value).
Your previous code of:
var object = $0
object.value = value
would have worked for reference types, but not for value types – as object here is simply a copy of $0, so any mutations won't be reflected in the array. Therefore you should annotate your protocol to make it clear that your protocol isn't designed to be used with value types.
If you do want to be able to handle value types, you may want to consider using map instead:
func updateElements<T:Base>(ofType type: T.Type, withValue value: Int) {
objects = objects.map {
var object = $0
if object is T {
object.value = value
}
return object
}
}
But this code works just fine.
protocol Base {
var value: Int { get set }
}
class ObjectTypeA: Base {
var value: Int = 0
}
class ObjectTypeB: Base {
var value: Int = 1
}
var objects: [Base] = [ObjectTypeA(), ObjectTypeB()]
func updatePropertyForType(type: Base.Type, value: Int) {
objects.filter({ object in
let result = object.dynamicType == type
return result
}).forEach {
var object = $0
object.value = value
}
}
updatePropertyForType(ObjectTypeB.self, value: 10)
print(objects)

How to reverse the Linked List in Swift extension?

I want to reverse the Single Linked List in extension, but finally it's failed.can someone help me? thanks.
public class List<T: Equatable> {
var value: T!
var nextItem: List<T>?
public convenience init!(_ values: T...) {
self.init(Array(values))
}
init!(var _ values: Array<T>) {
if values.count == 0 {
return nil
}
value = values.removeFirst()
nextItem = List(values)
}
}
// Reverse a linked list.
extension List {
func reverse() {
}
}
I have a solution here. Please read the comments, its all evident from the code too. Also I have added a 'description' via CustomStringConvertible to the list to help debugging and printing.
public class List<T: Equatable>{
var value: T!
var nextItem: List<T>?
public convenience init!(_ values: T...) {
self.init(Array(values))
}
init!(_ values: Array<T>) {
if values.count == 0 {
return nil
}
var valuesCopy = values
value = valuesCopy.removeFirst()
nextItem = List(Array(valuesCopy))
}
}
extension List : CustomStringConvertible{
public var description: String {
var desc = String()
var listRef : List<T>? = self
while listRef != nil {
desc += "\((listRef?.value)!) "
listRef = listRef?.nextItem
}
return desc
}
}
extension List{
func reverse() -> List?{
// Iterate through each item, and reverse its link until you visit the last node in the list.
// Once you reach the end, All items except the last one would have
// their links reversed.
var nextNode : List<T>? = self.nextItem
var prevNode : List<T>? = nil
var currentNode : List<T>? = self
while nextNode != nil{
currentNode?.nextItem = prevNode
prevNode = currentNode
currentNode = nextNode
nextNode = currentNode?.nextItem
}
//Ensure the last item in the list too has its links reversed.
currentNode?.nextItem = prevNode
return currentNode
}
}
var list = List(1,2,3,5)
print(list ?? "Failed to create the list")
if let reversed = list.reverse(){
print(reversed)
}

Swift 2 issue with a closure for groupBy collection

The code below is written in order to group journal publications by year of publication.
But I got the error "Cannot convert value of type '(Journal) -> Int' to expected argument type '(_) -> _'"
Here's the playground with a stripped down version of the real code for you to play around http://swiftlang.ng.bluemix.net/#/repl/1de81132cb2430962b248d2d6ff64922e2fe912b1480db6a7276c6a03047dd89
class Journal {
var releaseDate: Int = 0
static var journals = [Journal]()
class func groupedReduce<S: SequenceType, K: Hashable, U> (
source: S,
initial: U,
combine: (U, S.Generator.Element) -> U,
groupBy: (S.Generator.Element) -> K
)
-> [K:U]
{
var result: [K:U] = [:]
for element in source {
let key = groupBy(element)
result[key] = combine(result[key] ?? initial, element)
}
return result
}
class func groupBy() {
let byYear = { (journal: Journal) in
journal.releaseDate
}
let groupedJournals = groupedReduce(journals, initial: 0, combine:+, groupBy: byYear)
print("Grouped journals = \(groupedJournals)")
}
}
Journal.journals = [Journal(), Journal(), Journal(), Journal()]
for j in Journal.journals {
j.releaseDate = 1
}
Journal.groupBy()
Your code is overly complicated. Below is a groupBy function that group elements of an array according to criteria of your choice. Playground
import Foundation
class Journal {
var releaseDate: Int = 0
init(_ releaseDate: Int) {
self.releaseDate = releaseDate
}
}
extension Array {
func groupBy<T: Hashable>(f: Element -> T) -> [T: [Element]] {
var results = [T: [Element]]()
for element in self {
let key = f(element)
if results[key] == nil {
results[key] = [Element]()
}
results[key]!.append(element)
}
return results
}
func groupBy2<T: Hashable>(f: Element -> T) -> [T: [Element]] {
return self.reduce([T: [Element]]()) { (var aggregate, element) in
let key = f(element)
if aggregate[key] == nil {
aggregate[key] = [Element]()
}
aggregate[key]!.append(element)
return aggregate
}
}
}
let journals = [Journal(2015), Journal(2016), Journal(2015), Journal(2014)]
let groupedJournals = journals.groupBy {
$0.releaseDate
}
print(groupedJournals)

get the type/class of a property from its name in swift

Lets say I have this class:
class Node {
var value: String
var children: [Node]?
}
If I have the name of one of its properties (for example "children") how can I get its type? (In this case [Node]?)
I imagine having a global function like below will solve my needs:
func typeOfPropertyWithName(name: String, ofClass: AnyClass) -> AnyClass? {
//???
}
// Example usage:
var arrayOfNodesClass = typeOfPropertyWithName("children", Node.self)
Swift 2 (Note: Reflection changed):
import Foundation
enum PropertyTypes:String
{
case OptionalInt = "Optional<Int>"
case Int = "Int"
case OptionalString = "Optional<String>"
case String = "String"
//...
}
extension NSObject{
//returns the property type
func getTypeOfProperty(name:String)->String?
{
let type: Mirror = Mirror(reflecting:self)
for child in type.children {
if child.label! == name
{
return String(child.value.dynamicType)
}
}
return nil
}
//Property Type Comparison
func propertyIsOfType(propertyName:String, type:PropertyTypes)->Bool
{
if getTypeOfProperty(propertyName) == type.rawValue
{
return true
}
return false
}
}
custom class:
class Person : NSObject {
var id:Int?
var name : String?
var email : String?
var password : String?
var child:Person?
}
get the type of the "child" property:
let person = Person()
let type = person.getTypeOfProperty("child")
print(type!) //-> Optional<Person>
property type checking:
print( person.propertyIsOfType("email", type: PropertyTypes.OptionalInt) ) //--> false
print( person.propertyIsOfType("email", type: PropertyTypes.OptionalString) //--> true
or
if person.propertyIsOfType("email", type: PropertyTypes.OptionalString)
{
//true -> do something
}
else
{
//false -> do something
}
Reflection is achieved in Swift using the global reflect() function. When passing an instance of some type to reflect() it returns a MirrorType, which has a range of properties allowing you to analyze your instance:
var value: Any { get }
var valueType: Any.Type { get }
var objectIdentifier: ObjectIdentifier? { get }
var count: Int { get }
var summary: String { get }
var quickLookObject: QuickLookObject? { get }
var disposition: MirrorDisposition { get }
subscript(i: Int) -> (String, MirrorType) { get }
This seems to work:
func getTypeOfVariableWithName(name: String, inInstance instance: Any) -> String? {
let mirror = reflect(instance)
var variableCollection = [String: MirrorType]()
for item in 0..<mirror.count {
variableCollection[mirror[item].0] = mirror[item].1
}
if let type = variableCollection[name] {
let longName = _stdlib_getDemangledTypeName(type.value)
let shortName = split(longName, { $0 == "."}).last
return shortName ?? longName
}
return nil
}
Here's some example code on SwiftStub.
Edit:
The result for optional values is only "Optional".
The result for arrays is only "Array".
The result for dictionaries is only "Dictionary".
I'm not sure if it is possible to extract what kind of optional/array/dictionary it is. But I guess this would also be the case for custom data structures using generics.
Building on #PeterKreinz answer I needed to be able to check types of inherited properties as well so added a little to his above code:
extension NSObject {
// Returns the property type
func getTypeOfProperty (name: String) -> String? {
var type: Mirror = Mirror(reflecting: self)
for child in type.children {
if child.label! == name {
return String(child.value.dynamicType)
}
}
while let parent = type.superclassMirror() {
for child in parent.children {
if child.label! == name {
return String(child.value.dynamicType)
}
}
type = parent
}
return nil
}
}
Hope this may help someone.
Swift 3 update:
// Extends NSObject to add a function which returns property type
extension NSObject {
// Returns the property type
func getTypeOfProperty (_ name: String) -> String? {
var type: Mirror = Mirror(reflecting: self)
for child in type.children {
if child.label! == name {
return String(describing: type(of: child.value))
}
}
while let parent = type.superclassMirror {
for child in parent.children {
if child.label! == name {
return String(describing: type(of: child.value))
}
}
type = parent
}
return nil
}
}
The solution provided by #peter-kreinz using Swift's class Mirror works beautifully when you have an instance of a class, and want to know the types of the properties. However if you want to inspect the properties of a class without having an instance of it you might be interested in my solution.
I have a solution that finds the name and type of a property given any class that inherits from NSObject.
I wrote a lengthy explanation on StackOverflow here, and my project is available here on Github,
In short you can do something like this (but really check out the code Github):
public class func getTypesOfProperties(inClass clazz: NSObject.Type) -> Dictionary<String, Any>? {
var count = UInt32()
guard let properties = class_copyPropertyList(clazz, &count) else { return nil }
var types: Dictionary<String, Any> = [:]
for i in 0..<Int(count) {
guard let property: objc_property_t = properties[i], let name = getNameOf(property: property) else { continue }
let type = getTypeOf(property: property)
types[name] = type
}
free(properties)
return types
}