Data Hiding and Inheritance

In object-oriented languages that are stricter than Python, class data may be public or private. Public members are directly accessible from an instance. Private attributes can only be accessed through methods; the data is said to be encapsulated within the object. Private methods can only be accessed by other methods. This is to prevent outside code from changing the attributes, or the results of methods, without a “message” to the class instance being sent.

Data Hiding in Python

Python does not enforce this but does have a mechanism for “hiding” some members. All symbols beginning, but not ending, in two underscores are not accessible through an instance. They can only be utilized through a method. Symbols beginning with a single underscore are understood to be part of the implementation and not the interface. Outside code must not rely on them and should rarely to never use them directly.

Example:

class MyClass:
    """This is my class"""
    _i=12345
    #init is surrounded by double underscores
    def __init__(self,x,y):
        self.x=x
        self.y=y

    def reset(self,x,y):
        self.x=x
        self.y=y

    def __redo(self):  #double underscore
        self.x=10.
        self.y=20.

    def addit(self,z):
        return MyClass._i+self.y-z


This makes a difference.

ac=MyClass(19.,20.)
ac.addit(30.)
ac._i
ac.__redo()

The last line will result in an AttributeError: MyClass instance has no attribute ‘__redo’.

However, it is not absolute:

ac._MyClass__redo()   #impolite!
print(ac.x,ac.y)

Accessors and Mutators

To handle “private” or even just “implementation” variables we use methods. Accessors (“getters”) get the value and return it. Mutators (“setters”) change the value.

class PrivateStuff:
      def __init__(self,x):
          self.__u=11.
          self.x=x
      def set_u(self,u):
          self.__u=u
      def get_u(self):
          return self.__u
secret=PrivateStuff(9.)
u1=secret.get_u()
print(u1)
secret.set_u(12.)
u2=secret.get_u()
print(u2)

Inheritance: New Classes from Old

One of the cornerstones of Object-Oriented Programming is inheritance. New classes can be derived from existing classes; the lower-level class is called the base class. The derived class inherits the attributes and methods from its parent. The new class is said to be a subclass of its parent.

Inheritance facilitates code reuse and extension of code functionality while minimizing the modifications required to the original code. The new class may add members, both attributes and methods, along with the inherited ones. It can also override the methods of the base class, adapting them to the requirements of the new class. No changes to the base class are required.

The relationship between the base class and the derived class can be understood as “Child IS_A Parent.”

Examples

A Sparrow IS_A Bird
An Employee IS_A Person

Let us consider a more detailed example. An important object in a forest model is a tree. An individual tree will have particular attributes depending on the species, and they may have additional behaviors in some cases, but they will have a number of attributes in common. We can define a class Species which might contain attributes such as

  • genus
  • species
  • wood_density
  • max_life_expectancy
  • max_height The methods would include behaviors such as
  • sprout
  • grow
  • die

A Tree would add members specific to an individual tree, such as

  • diameter
  • height
  • branch

In Python, we indicate the parent with parentheses

class Child(Parent):

Example

Suppose we wish to develop code for an employee class when we already have a Person class. Person defines general data such as name and address. The additional attributes for Employee will be the employee’s salary and ID number.

class Person:
    def __init__(self,name,address):
        self.name=name
        self.address=address

    def getName(self):
        return self.name

    def getAddress(self):
        return self.address

class Employee(Person):
    def __init__(self,name,address,employee_id,salary):
        Person.__init__(self,name,address)
        self.employee_id=employee_id
        self.salary=salary

    def setSalary(self,salary):
        self.salary=salary

    def getSalary(self):
        return self.salary

    def getID(self):
        return self.employee_id

name="Tom Jones"
address="1234 Mystreet, Thecity"
employee_id=6789
salary=45000.
an_employee=Employee(name,address,employee_id,salary)

print("Employee " +an_employee.getName() + " lives at " +an_employee.getAddress()  + " and makes $" + str(an_employee.getSalary()))

Previous
Next