0

I am taking a Data Structures course in Java and to help myself learn Swift I am trying to complete the same assignments I have already done in Java in Swift. I am having some trouble comparing Objects in Swift. In Java, I have the following ArrayList Class with a remove(E obj) method:

public E remove(E obj) {
        if (currentSize == 0){
            return null;
        }
        for (int i=0; i<currentSize; i++)
            if (((Comparable<E>)storage[i]).compareTo(obj) == 0) {
                E removedElement = storage[i];
                for (int j = i;j<currentSize-1;j++) {
                    storage[j] = storage[j+1];
                }
                currentSize--;
                if (currentSize < 0.25*maxSize)
                    shrinkStorage();
                return removedElement;
            }
        return null;
    } 

This goes through the list and casts each element in the list to Comparable and compares it to the object.

Now, translating this into Swift I created the a ArrayLinearList structure and made this function

mutating func remove(obj: E) -> E? {
        if currentSize == 0 {
            return nil
        }
        for var i = 0; i < currentSize; i++ {
            if storage[i] == obj {
                let removedElement = storage[i]
                for var j = 1; j < currentSize-1; j++ {
                    storage[j] = storage[j+1]
                }
                currentSize--
                if currentSize < maxSize/4 {
                    shrinkStorage()
                }
                return removedElement
            }
        }
        return nil
    }

I read the documentation on the Comparable and Equatable interface online but it was my understanding that the implementation of the Comparable and Equatable interface should be in the actual class to be used. on this line

if storage[i] == obj {

Cannot invoke '==' with an argument list of type '($T6,E)'

What is the proper way to set this up so I can compare generic objects in my structure? In case it is important, the generic array is declared as:

var storage = [E]()
2
  • 1
    As an aside - since you said you're learning Swift - it would be more "Swift-like" to write your for loops with the range syntax: for i in 0..<currentSize { ... }. Commented Mar 28, 2015 at 7:21
  • You're doing something unsafe in Java if you have to explicitly cast to Comparable<E>. Also, doing .compareTo() and then checking == 0 is silly and you should always do .equals() instead. Commented Mar 29, 2015 at 7:34

1 Answer 1

2

Well you almost had it. You just need to adhere to the Equatable protocol for type E and it should all work fine. Generic types in swift can adhere to protocols in order to make sure that the type you are passing can do certain operations. In this case be compared. This is good since you will not be able to use your struct with types that don't adhere to the protocol which will reduce runtime errors due to unexpected methods.

Here is what I did to get rid of the warning.

struct ArrayLinearList<E: Equatable> {

    var currentSize = 0;
    var maxSize = 10;
    var storage = [E]();

    mutating func remove(obj: E) -> E? {

        if currentSize == 0 {
            return nil
        }

        for var i = 0; i < currentSize; i++ {
            if storage[i] == obj {
                let removedElement = storage[i]

                for var j = 1; j < currentSize-1; j++ {
                    storage[j] = storage[j+1]
                }

                currentSize--

                if currentSize < maxSize/4 {
                    shrinkStorage()
                }

                return removedElement

            }

        }

        return nil

    }

    func shrinkStorage() {

    }
}

As for the confusion with the protocol interfaces, since you are not defining your own type you don't need to implement these interface. You just care that two things can be equal so having <E: Equatable> is enough to tell the compiler "hey, this function works with all types that have implemented the Equatable interface". If you want to use a custom type that you create and compare two instances then you will need to implement the interface for that type.

Hope that helps.

Sign up to request clarification or add additional context in comments.

2 Comments

Yes that totally makes sense. So if I was doing an ordered list I probably would write struct ArrayLinearList<E: Comparable> which inherits from Equatable correct?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.