Assigning UITableView delegate and dataSource to super

I am trying to have a super class fill and handle the contents of a table for a certain segment. So I thought of implementing:

    @IBAction func changeValue(sender:AnyObject){
        self.searchDisplayController?.setActive(false, animated:false)
        if (selection.selectedSegmentIndex==1){
            self.myTableView.delegate=super
            self.myTableView.dataSource=super
        } else {
            self.myTableView.delegate=self
            self.myTableView.dataSource=self
        }
        self.myTableView.reloadData()
    }

Yet I had an error. By way of testing, the compiler suggested me to use:

    @IBAction func changeValue(sender:AnyObject){
        self.searchDisplayController?.setActive(false, animated:false)
        if (selection.selectedSegmentIndex==1){
            self.myTableView.delegate=super.self()
            self.myTableView.dataSource=super.self()
            print("type: \(super.self())")
        } else {
            self.myTableView.delegate=self
            self.myTableView.dataSource=self
        }
        self.myTableView.reloadData()
    }

whatever the meaning of construct super.self()

Yet, notwithstanding the code passes through there without any problem, the command seems to be ignored and the delegate methods are called on the same class instead of the super one and even printing the value of super.self() shows it is the current class, notwitstanding, when I skip the (), Xcode encourges me by saying:

Function produces expected type 'LogsViewController'; did you mean to call it with '()'?

Yet when I add the double parenthesis it return the current class instead of the top LogsViewController.

What is the correct way of implementing what I need, and why super.self() does not work as it is advertised?


I am reporting the cehma of my pattern implmentation, should it be unclear:


Bottom class:

override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        /
        /
        let isMainTable = tableView==self.myTableView
        let isFavorite = selection.selectedSegmentIndex==2
        var count: Int?
        count = sourceForTableKind(isMainTable, favorites:isFavorite)?.count
        if (count==nil) {
            return 0
        }
        return count!
    }


Top "virtual" class:

    func sourceArray()->Array<NearElement>?{
        return nil
    }

    func arrayOfContentsFromSearchArray(searchArray:Array<String>?, favorites:Bool)->Array<NearElement>?{
        return nil
    }

    func sourceForTableKind(normal: Bool, favorites:Bool)->Array<NearElement>?{
        /
        print("sono \(self)")
        if (normal) {
            return sourceArray()
        } else {
            return arrayOfContentsFromSearchArray(searchResults, favorites:favorites)
        }
    }

Accepted Reply

I ended up, as also suggested, by calling the super on all delegate methods. Of course it would have been cleaner to switch the table or its delegate and dataSource to the top class, but that simply does not work in Swift.

Yet, even this pushes the virtual function to call the bottom implementations. Calling the top delegate methods does not apparently change the active instance the virtual function finds when implementing its methods. Of course I will need to awkwardly send upwards even the implementations, but this is definitely a bug of the support and a departure from OO established patters.

Replies

In Swift, `self` represents the instance itself when used in an instance context. But `super` does not represent any sort of concrete instances. It is just a prefix to choose superclass's method.


In your case, this line:

            self.myTableView.delegate=super.self()

is just calling `self` method. (It is a method without arguments, so you need `()` to call the method.)

- self (NSObject Protocol Reference)

I believe you are not overriding this `self` method, thus, calling super's `self` is exactly the same as calling self's `self`.

            self.myTableView.delegate=self.`self`()


If you need an instance having the behavior of the super class, you need to instantiate the super class explicitly. Keyword `super` does not create an instance of the super class.

And how how would I instantiate it? It is a ViewController rooted in the storyboard.

Moreover what I need is its, so to say, point of view, not a concrete instance.

What I am trying to implement is a quite common usage of the Template pattern from the Gang of Four's set. I need to execute the virtual functions from the point of view of the top class, so that its instances are called instead of those of the bottom class?


Moreover I am quite unclear why the compiler hints to the top class name when I enter self.super, suggesting me to enter (), but when I do it self.super() becomes self. I think there is at least a bug in the support.

I added the sample code to explain my issue.

I ended up, as also suggested, by calling the super on all delegate methods. Of course it would have been cleaner to switch the table or its delegate and dataSource to the top class, but that simply does not work in Swift.

Yet, even this pushes the virtual function to call the bottom implementations. Calling the top delegate methods does not apparently change the active instance the virtual function finds when implementing its methods. Of course I will need to awkwardly send upwards even the implementations, but this is definitely a bug of the support and a departure from OO established patters.

I would disagree. Polymorphism is one of the key concepts of object-oriented programming. Of course method calls will be dispatched to the "lowest" class that implements that method. If you want to use the superclass's implementation, you have to either call the superclass's implementation yourself in your overridden method, or don't override that method in the first place.


There is only one object. It is an instance of both the subclass and the superclass at the same time. There is only one "self".

What I found reading the additional code and your reply is you were misunderstanding Template pattern and confusing self.super and super.self .


ADDITION: I need to add one more thing. This nature of Swift's `super` is common with Java or C#(base) or many other OO language. You cannot write the similar code even in Java, the origin of Gang of Four.

I wrote some `virtual` code in Java.

TableViewDatasource.java:

public interface TableViewDatasource {
    int numberOfSections();
    int numberOfRowsInSection(int section);
    //...
}


TableView.java:

public class TableView {
    TableViewDatasource datasource;
    //...
}


TopVirtualViewController.java:

public abstract class TopVirtualViewController implements TableViewDatasource {
    protected TableView tableView;

    TopVirtualViewController() {
        this.tableView = new TableView();
    }


    @Override
    public int numberOfSections() {
        return 1;
    }


    @Override
    public int numberOfRowsInSection(int section) {
        return 1;
    }

    //...
}


BottomViewController.java:

public class BottomViewController extends TopVirtualViewController {

    public void changeValue(Object sender) {
        this.tableView.datasource = super; //-> got error: '.' expected
    }

    @Override
    public int numberOfSections() {
        return 2;
    }

    @Override
    public int numberOfRowsInSection(int section) {
        return 2;
    }

    //...
}


Do you think this is a bug of the support and a departure from OO established patters ?