\documentclass[14pt,compress,aspectratio=169]{beamer}

\usepackage{hyperref}
\input{macros.tex}


\title[OOP: multiple inheritance]{Advanced Python}
\subtitle{Object Oriented Programming: Multiple Inheritance}

\author[FOSSEE] {The FOSSEE Group}

\institute[IIT Bombay] {Department of Aerospace Engineering\\IIT Bombay}
\date[] {Mumbai, India}

\begin{document}

\begin{frame}
  \titlepage
\end{frame}

\begin{frame}[fragile]
  \frametitle{Overview}
  \begin{itemize}
  \item Thus far, single inheritance
  \end{itemize}
  \begin{lstlisting}
    class Animal:
        def greet(self): ...

    class Cat(Animal):
        def greet(self): ...

    class Dog(Animal):
        def greet(self): ...
\end{lstlisting}
\end{frame}

\begin{frame}[fragile]
  \frametitle{Motivation}
  \begin{itemize}
  \item What if you wanted two parents?
  \end{itemize}

\begin{lstlisting}
class Animal:
    def eat(self): pass
  \end{lstlisting}
  \pause
  \begin{lstlisting}
class Mammal(Animal):
    def hair_color(self): pass
  \end{lstlisting}
  \pause
\begin{lstlisting}
class FlyingAnimal(Animal):
    def fly(self): pass

\end{lstlisting}
\end{frame}

\begin{frame}[fragile]
  \frametitle{Motivation \ldots}
\begin{lstlisting}
class Bat(Mammal, FlyingAnimal):
    pass

In []: b = Bat()

In []: b.eat(), b.hair_color(), b.fly()
\end{lstlisting}
\vspace*{0.25in}
\footnotesize{Example from \href{https://en.wikipedia.org/wiki/Virtual_inheritance}{Wikipedia}}
\end{frame}


\begin{frame}
  \frametitle{Observations}
  \begin{itemize}
  \item \py{Mammal} is an \py{Animal}
  \item \py{FlyingAnimal} is an \py{Animal}
  \item \py{FlyingAnimal} is not a \py{Mammal}
  \item \py{Bat} is a \py{Mammal} and a \py{FlyingAnimal}
  \end{itemize}
\end{frame}

\begin{frame}[fragile, plain]
  \frametitle{Multiple inheritance and super}
  \small
  \vspace*{-0.1in}
  \begin{lstlisting}
class Base:
    def __init__(self):
        print('Base')

class A(Base):
    def __init__(self):
        print('A')
        super().__init__()

class B(Base):
    def __init__(self):
        print('B')
        super().__init__()

  \end{lstlisting}

\end{frame}

\begin{frame}[fragile]
  \frametitle{Multiple inheritance and super}
  \small
  \begin{lstlisting}
class C(A, B):
    def __init__(self):
        print('C')
        super().__init__()

In []: c = C()
C
A
B
Base
\end{lstlisting}

\end{frame}


\begin{frame}[fragile]
  \frametitle{Changing the order of parents}
  \small
  \begin{lstlisting}
class C1(B, A):
    def __init__(self):
        print('C1')
        super().__init__()

In []: c1 = C1()
C1
B
A
Base
\end{lstlisting}
\end{frame}

\begin{frame}[fragile]
  \frametitle{\py{mro}:  method resolution order}
  \begin{itemize}
  \item \py{mro} method shows order of calls
  \item A method on the class object, not the instance
  \end{itemize}
  \begin{lstlisting}
In []: C.mro()
Out[]: [__main__.C, __main__.A, __main__.B,
        __main__.Base, object]

In []: C1.mro()
Out[]: [__main__.C1, __main__.B, __main__.A,
        __main__.Base, object]
  \end{lstlisting}
\end{frame}

\begin{frame}[fragile, plain]
  \frametitle{Another example}
  \small
  \vspace*{-0.1in}
  \begin{lstlisting}
class A:
    def __init__(self):
        print('A')
class B:
    def __init__(self):
        print('B')

class C(A, B):
    def __init__(self):
        print('C')
        super().__init__()

In []: c = C()
C
A
\end{lstlisting}

\end{frame}

\begin{frame}
  \frametitle{Observations}
  \begin{itemize}
  \item \py{A} and \py{B} did not call \py{super}
  \item \py{super} is what calls the parent \py{__init__}
  \item The order of calls is determined by \py{mro}
  \item This works for any method, not just \py{__init__}
  \end{itemize}
\end{frame}

\begin{frame}[fragile]
  \frametitle{Question}
  \begin{itemize}
  \item What if \py{C} did not call \py{super}?
  \end{itemize}
  \begin{lstlisting}
class C(A, B):
    def __init__(self):
        print('C')

In []: c = C()
  \end{lstlisting}
\end{frame}

\begin{frame}
  \frametitle{Learning more}
  \begin{itemize}
  \item See: \url{docs.python.org/3.6/tutorial/classes.html}
  \item See: \url{www.python.org/download/releases/2.3/mro/}
  \end{itemize}
\end{frame}

\begin{frame}
  \frametitle{Summary}
  \begin{itemize}
  \item Multiple base classes
  \item Important of \py{super}
  \item \py{mro} determines order of calls
  \end{itemize}
\end{frame}


\end{document}
