Skip to content

Instantly share code, notes, and snippets.

@dudeisbrendan03
Last active March 8, 2021 16:35
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dudeisbrendan03/f5648987af79b4dceb86fa322e345e35 to your computer and use it in GitHub Desktop.
Save dudeisbrendan03/f5648987af79b4dceb86fa322e345e35 to your computer and use it in GitHub Desktop.
Object-Oriented Languages

Object Oriented Programming (OOP)

What is OOP

  • Capture, group info, data and related functionality into 'objects'

  • OOP world viewed as collection as objects

  • Abstract data like unique data structures, user accounts etc

  • Each object responsible for it's own data and operations performed in that data (scope)

  • Objects can interact with eachother

What's in an object

  • A class
    • Class name
    • Attribute
      • All of the information share dby any object of this class type
    • Methods
      • Code associated with the class tha tallows you to access or change it's attributes
  • A class is not an object itself.
  • Very easy to reuse a calss and create multiple objects of that class
  • Classes are in itself not an object, more of a template for one
  • To create an object from a class, we go through a process called instansiation (initialising a class into an object)

ClassName() 
    --> Constructor
        --> Attributes set (variables local to the class and any instantised objects from this class)
            --> SomeAttribute(String)
            --> AnotherAttribute(Integer)
    --> Methods
        --> myMethod()
        --> anotherMethod()

Above is an example of a class, a class itself does not serve much of a purpose, it's like a 'template' for an object

new ClassName(SomeAttribute, AnotherAttribute) -> something

Above is an example of us using that class to create an object called 'something'. We can call methods and set attributes of something based of the attributes and methods defined in the class, ClassName.

OOP in practice

  • Implementation varies language to language (surprise)
  • Similar structure between all languages
    • Langauges class keyword then class name
    • Break out of the indendation or a marker that indicates the end of the class
    • Attributes for the class
    • Parameters and code for the instantiation of the class (e.g. _init_ in python)
      • Called a "constructor" method
      • Can be used to set local attributes before methods used

Example implementation in python

Example of a class without any paramters in Python:

"""
Example of a class being implemented in python
"""

class SomeClass(object): #A class is pretty much a template of an object

    def __init__(self):
        #self in python is the local scope of an object after instantised
        self.somevar = "Something"

Example of a class with parameters in Python:

class SomeClass(object):

    def __init__(self,somePassedVariable):
        self.somevar = somePassedVariable # This variable is now locally available in any instantised object made from this class

Example of a class with a single method being instantised into it's own object:

class SomeClass(object):
    
    def __init__(self,somePassedVariable):
        self.somevar = somePassedVariable

    def myMethod(self):
        print(self.somevar)

myObject = SomeClass()
>> Parameter error
# You must always try to initialise a class with all required parameters inside of it's constructor method, unless the constructor provides a default

myObject = SomeClass("A string")
>> myObject -> new SomeClass ("A string")
# We now have an object stored inside myObject which represents a copy of SomeClass

myObject.myMethod()
>> "A string"
# Thanks to our class, the object has a single method which uses a variable stored locally inside the class when we initialised it, here we call a method which utilises that variable

Static methods/functions

A static function is a function which never leaves the scope of this, the local scope to that instance of an object (from a class).

class SomeClass(object):
    def __init__(self,someVar):
        self.somevar = someVar
    
    @staticmethod
    def myStaticMethod():
        return "I never interact with anything in the local scope"

    def myNoneStaticMethod(self):
        return self.somevar

example = SomeClass("I do!")
example.myStaticMethod()
>> "I never interact with anything in the local scope"

example.myNoneStaticMethod()
>> "I do!"

Extending a class

For examples in this section I'll extend from the class here:


myClass() 
    --> Constructor
        --> SomeAttribute(String)
        --> AnotherAttribute(Integer)
    --> Methods
        --> myMethod()
            > return "Hello, world!"
        --> anotherMethod(varPassedIntoMethod)
            > return varPassedIntoMethod + self.AnotherAttribute

#Implementation of the above class
new myClass(
    SomeAttribute = "hello"
    AnotherAttribute = 2
) -> something

something.myMethod()
>> "Hello, world!"

something.anotherMethod(3)
>> 5

Inheritance

One can extend an existing class, using a class as a template for another class.

This decreases code replication and allows for simpler implementation of objects. Having a generic class makes it easier to implement multiple similar classes- we can reuse an existing class, using it's attributes and methods, without affecting the original code.


anotherClass(myClass)
    # This extends myClass - we need a class with the same methods as myClass, which also carries another method for something else we may need to do
    --> Constructor
        --> VeryImportantAttribute(String)
    --> Methods
        --> veryImportantExtraMethod()
            > return self.VeryImportantAttribute + ", world!"

#Implementation of the above class
new anotherClass(
    SomeAttribute = "hello"
    AnotherAttribute = 2
    VeryImportantAttribute = "goodbye"
) -> something

something.myMethod()
>> "Hello, world!"

something.anotherMethod(3)
>> 5

something.veryImportantExtraMethod()
>> "Goodbye, world!"

Here anotherClass has inherited the same methods and attributes of myClass, we only add the new parts of the class we require. This is called a subclass- a child which extends another class. Whereas myClass (in context of anotherClass), is a superclass- a parent to a, or multiple, child classes.

A subclass and superclass is always context related, we could have more classes inherited from anotherClass, these classes would see anotherClass as it's super class.

There is no limit1 to how far you may branch a class.

1 Theoretically in implementation, there may be limits in specific languages, or proposed by system resources

Overriding

We can override standard inheritance by simply having an attribute or method which is identified the same way in a subclass as it's superclass

For example if anotherClass.myMethod was defined when creating the extension of myClass, the implementation of myClass.myMethod would not be inherited by anotherClass.


anotherClass(myClass)
    # This extends myClass - we need a class with the same methods as myClass, which also carries another method for something else we may need to do
    --> Constructor
        --> VeryImportantAttribute(String)
    --> Methods
        --> veryImportantExtraMethod()
            > return self.VeryImportantAttribute + ", world!"
        --> myMethod()
            > return "This is completely unrelated to myClass"

#Implementation of the above class
new anotherClass(
    SomeAttribute = "hello"
    AnotherAttribute = 2
    VeryImportantAttribute = "goodbye"
) -> something

something.myMethod()
>> "This is completely unrelated to myClass"

something.anotherMethod(3)
>> 5

something.veryImportantExtraMethod()
>> "Goodbye, world!"

An original method can still be obtained in most object-oriented programming langauges. This is done by called the superclass inside the subclass, as the original structure of the parent should always be stored.

something.super.myMethod()
>> "Hello, world!"

Example implementation in python

class myClass(object):
    def __init__(self,SomeAttribute,AnotherAttribute) -> None: # A superclass to the other classes
        self.SomeAttribute = SomeAttribute
        self.AnotherAttribute = AnotherAttribute
    
    @staticmethod
    def myMethod()
        return "Hello, world!"

    def anotherMethod(varPassedIntoMethod):
        return varPassedIntoMethod + self.AnotherAttribute

class anotherClass(myClass): # A subclass showing inheritance
    def __init__(self,SomeAttribute,AnotherAttribute,VeryImportantAttribute):
        super().__init__() # In python to avoid rewriting the superclass constructor method, we can call it
        self.VeryImportantAttribute = VeryImportantAttribute

    def veryImportantExtraMethod(self):
        return self.VeryImportantAttribute + ", world!"

class myOverrideClass(myClass): # A subclass showing overridden methods
    def __init__(self,SomeAttribute,AnotherAttribute): # A superclass to the other classes
        super().__init__()

    @staticmethod
    def myMethod(self):
        return "This is completely unrelated to myClass"


exampleStandardClass = myClass("Something",123)
myClass.myMethod()
>> "Hello, world!"

myClass.anotherMethod(3)
>> 125

exampleInheritedClass = anotherClass("Something",321,"Goodbye")
exampleInheritedClass.myMethod()
>> "Hello, world!"

exampleInheritedClass.anotherMethod(2)
>> 323

exampleInheritedClass.veryImportantMethod("aaaa", 1337)
>> "Goodbye, world!"

overrideClass = myOverrideClass()
overrideClass.myClass()
>> "This is completely unrelated to myClass"

overrideClass.super().myClass()
>> "Hello, world!"

overrideClass.anotherMethod(1)
>> 1338

Encapsulation

Encapsulation is about protecting certain contents of an initialised class, an object.

  • The "bundling of data with the methods that operate on and restrict direct access to it"
  • Is used to hide value sor states of an obejct
  • Encapsulised attributes should only be accessible or changable by the methods provided by the object
  • Keeps data related to an object safe- can't be accidentally modified by other methods
  • Protected attributes act like a variable/attribute stored locally somewhere else, attempting to access it will return an error/exception in the implementation like it doesn't exist (unless accessed through the method required)

Implementation:

  • You must supply methods if you want an objects internal attributes to be read/written
  • An objects methods are usually public, not private
  • The methods are the part of of the same object, so it's private attributes are available
  • Every language has it's own unique way to implement protected members
class Person:
  def __init__(self): 
    self.name = 'Some'
    self.__lastname = 'Person'
    
  def PrintName(self):
    return self.name +' ' + self.__lastname#Inside the class, or once instantised an object, we can view and edit __lastname
    
#Outside class    
P = Person()
print(P.name)
>> "Some"
print(P.PrintName())
>> "Some Person"
print(P.__lastname)#When accessing this outside the object however, not going through a method, we get an error as if the attribute does not exist
>> Exception: AttributeError: 'Person' object has no attribute '__lastname'

Polymorphism

  • Polymorphism just means many forms
  • You're likely to of used it before
    • Example in Python
      a = "Hello"
      b = ", world!
      print(a+b) # String concatentation
      >> "Hello, world!"
      
      a = 1
      b = 2
      print(a+b) # Math operator
      >> 3
    • As you can see above, in both cases of print(a+b) we had completely different operations
  • OOP has two types of polymorphism
    • Static
      • Multiple methods of the same name, with different parameters in the same class
      • Also known as "method overloading"
      • In order for this to work it must differ in at least one of the following ways:
        • They need to have a different number of parameters
        • The types of parameters are different
        • They expect the parameters in a different order (bad practice)
    • Dynamic
      • Some things to remember
        • A subclass can override a superclass
        • An overriden superclass means we can completely replace or customise the behaviour of that specific method we override, acting like a completely new method
      • Overriding a method of a superclass in a subclass is a form of polymorphism
        • This is as they share the same name and parameters, but have different functionality depending on how they're implemented

Key questions

What is the difference between and object and a class?

A class is more of a template for an object which could be instantised in the future.

What is inheritance and how can it be used?

Inheritence is where you create a class as a subclass of another class, allowing it to have similar attributes and methods, which can be re-used or altered.

How can overriding be used in object-oriented programming?

To replace a method which is unfit for the usecase of a more specific/specialised implementation of a class.

What is encapsulation and how does it help to create a robust program?

Encapsulation allows us to protect attributes inside of an instantised class (an object), and therefore means we can not accidentally modify an attribute we wish to protect or of high importance, forcing us to interact with it through a method.

What is polymorphism and how can it be used?

Polymorphism allows us to have different use-cases of a single method, allowing us to implement some code in the same way for all uses, but run different operations on fed data.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment