When Should I Use "This" in a Class

When should I be using classes in Python?

Classes are the pillar of Object Oriented Programming. OOP is highly concerned with code organization, reusability, and encapsulation.

First, a disclaimer: OOP is partially in contrast to Functional Programming, which is a different paradigm used a lot in Python. Not everyone who programs in Python (or surely most languages) uses OOP. You can do a lot in Java 8 that isn't very Object Oriented. If you don't want to use OOP, then don't. If you're just writing one-off scripts to process data that you'll never use again, then keep writing the way you are.

However, there are a lot of reasons to use OOP.

Some reasons:

  • Organization:
    OOP defines well known and standard ways of describing and defining both data and procedure in code. Both data and procedure can be stored at varying levels of definition (in different classes), and there are standard ways about talking about these definitions. That is, if you use OOP in a standard way, it will help your later self and others understand, edit, and use your code. Also, instead of using a complex, arbitrary data storage mechanism (dicts of dicts or lists or dicts or lists of dicts of sets, or whatever), you can name pieces of data structures and conveniently refer to them.

  • State: OOP helps you define and keep track of state. For instance, in a classic example, if you're creating a program that processes students (for instance, a grade program), you can keep all the info you need about them in one spot (name, age, gender, grade level, courses, grades, teachers, peers, diet, special needs, etc.), and this data is persisted as long as the object is alive, and is easily accessible.

  • Encapsulation:
    With encapsulation, procedure and data are stored together. Methods (an OOP term for functions) are defined right alongside the data that they operate on and produce. In a language like Java that allows for access control, or in Python, depending upon how you describe your public API, this means that methods and data can be hidden from the user. What this means is that if you need or want to change code, you can do whatever you want to the implementation of the code, but keep the public APIs the same.

  • Inheritance:
    Inheritance allows you to define data and procedure in one place (in one class), and then override or extend that functionality later. For instance, in Python, I often see people creating subclasses of the dict class in order to add additional functionality. A common change is overriding the method that throws an exception when a key is requested from a dictionary that doesn't exist to give a default value based on an unknown key. This allows you to extend your own code now or later, allow others to extend your code, and allows you to extend other people's code.

  • Reusability: All of these reasons and others allow for greater reusability of code. Object oriented code allows you to write solid (tested) code once, and then reuse over and over. If you need to tweak something for your specific use case, you can inherit from an existing class and overwrite the existing behavior. If you need to change something, you can change it all while maintaining the existing public method signatures, and no one is the wiser (hopefully).

Again, there are several reasons not to use OOP, and you don't need to. But luckily with a language like Python, you can use just a little bit or a lot, it's up to you.

An example of the student use case (no guarantee on code quality, just an example):

Object Oriented

class Student(object):
def __init__(self, name, age, gender, level, grades=None):
self.name = name
self.age = age
self.gender = gender
self.level = level
self.grades = grades or {}

def setGrade(self, course, grade):
self.grades[course] = grade

def getGrade(self, course):
return self.grades[course]

def getGPA(self):
return sum(self.grades.values())/len(self.grades)

# Define some students
john = Student("John", 12, "male", 6, {"math":3.3})
jane = Student("Jane", 12, "female", 6, {"math":3.5})

# Now we can get to the grades easily
print(john.getGPA())
print(jane.getGPA())

Standard Dict

def calculateGPA(gradeDict):
return sum(gradeDict.values())/len(gradeDict)

students = {}
# We can set the keys to variables so we might minimize typos
name, age, gender, level, grades = "name", "age", "gender", "level", "grades"
john, jane = "john", "jane"
math = "math"
students[john] = {}
students[john][age] = 12
students[john][gender] = "male"
students[john][level] = 6
students[john][grades] = {math:3.3}

students[jane] = {}
students[jane][age] = 12
students[jane][gender] = "female"
students[jane][level] = 6
students[jane][grades] = {math:3.5}

# At this point, we need to remember who the students are and where the grades are stored. Not a huge deal, but avoided by OOP.
print(calculateGPA(students[john][grades]))
print(calculateGPA(students[jane][grades]))

Why do you have to use keyword this instead of class name?

Because in JavaScript, when you specify a class name (in particular, inside a class), you get a reference to the class, not to the current class instance. The instance properties and methods are not available through its class. Meanwhile this represents the current instance.

class App {
test() {
console.log(App); // "class App ..."
console.log(this); // "[object Object]"
console.log(App.foo()); // "1"
console.log(this.foo()); // "2"
console.log(this.constructor.foo()); // "1"; this.constructor is a reference to the current object class
}

static foo() {
return 1;
}

foo() {
return 2;
}
}

When do you use the this keyword?

There are several usages of this keyword in C#.

  1. To qualify members hidden by similar name
  2. To have an object pass itself as a parameter to other methods
  3. To have an object return itself from a method
  4. To declare indexers
  5. To declare extension methods
  6. To pass parameters between constructors
  7. To internally reassign value type (struct) value.
  8. To invoke an extension method on the current instance
  9. To cast itself to another type
  10. To chain constructors defined in the same class

You can avoid the first usage by not having member and local variables with the same name in scope, for example by following common naming conventions and using properties (Pascal case) instead of fields (camel case) to avoid colliding with local variables (also camel case). In C# 3.0 fields can be converted to properties easily by using auto-implemented properties.

Should I use this to call class properties, members, or methods?

Having gone from using this for years, to finding not many people (atleast in my experience) use it, I eventually changed. The benefits I can see of having this-less code:

  • I use underscores: _myVar for private variables, which don't need a this as they're always member variables.
  • For method calls it is very obvious that it's part of the class. You would prepend the type name if it wasn't.
  • (C#) Private variables and parameters are always camel case.
  • If your class is so big it's getting confusing you've got an issue with cohesion and separation of concerns anyway.
  • (C#) Visual Studio color codes types, so you know if you're using a property or type:

e.g.

someclass.Method(1);
SomeClass.StaticMethod(1);

I can see that if you don't use the underscores naming convention, and have a large method with a weighty body it could lead to some confusion.

Static methods or properties can occasionally confuse things, but very rarely.

You will obviously always need the this keyword when passing references, for example:

someclass.Method(this);
var someclass = new SomeClass(this);

(I write C#, but my answer relates to Java)

When should we use class and when we should not

The most important thing for a programmer in PHP, in my opinion, other than his experience is his toolkit. That is, code that he/she has written inside and out, backwards and forwards since time immemorial.

To me, in this instance, the advantage of OOP in clear. Having a class that you know will always preform what you want through simple methods is much easier for both yourself and team members, then it is by just calling a multitude of static functions. While you could argue a library of satic function includes serves the same purpose, in my opinion classes are much easier to read and understand. For example, in my custom session class a programmer can look at my code and see,

$my_session = new session();
$my_session->start();

if ( ($session_errno = $my_session->error()) !== FALSE)
{
//DO SOMETHING BECAUSE OF A SESSION ERROR
}

and easily understand that sessions in this application are handled via our custom session class, and should return some type of success/failure without having ever examined the library/class. Meanwhile, a call such as this,

session_start();

if (session_error())
{
//DO SOMETHING BECAUSE OF A SESSION ERROR
}

does not make it clear that session_start() is not a default PHP session handler, but that it will call the functions defined in session_set_save_handler() which was included in some mega list of global includes that might not be easily to locate in a large application. It is also not as clear that session_error() is a function that returns an error set by the custom session handler, vs a function that may actively look for session issues on an already generated session and is completely independent of PHP's default session.

This is not a great example, but I think it is a good one. I did not go into detail on the goodness that is protecting data from the application at whole, inheritance, and everything else that makes OOP useful.

But quickly, imagine a class that accesses an application's MYSQL database. A lot of time is spent designing the class to use prepared statements, log errors and provide proper logic to the programmer as needed. A team can worry less about database access issues by simply calling the class's public 'data access' functions without much concern about fatal errors, bad logic or dangerous SQL (injections and such).

This can all be done with static functions like you suggest, BUT every function in that static library is exposed to the application as a whole, while only the public and 'SAFE' functions are exposed to the application that uses a database access object. The programmer can not accidentally call a dangerous function that if not properly initialized by other functions could cause major issues, nor could the programmer deliberately suppress errors or other data protected by the class like they could with a slew of static functions and global variables.

While a good application can be designed without any objects, a good programmer should enjoy the usability, extensibility, and protections that objects afford when appropriate.

I'll leave with my final metaphor. Objects are like specialized machines and tools inside a factory. While the factory itself has a number of these unique tools on its assembly line, everything from simple bending brakes to CNC machines and automated robots, they are only a small part of the team that exists to help the more numerous laborers and managers, our static functions, do the job of building a better car, truck, or bike.

When should you use a class vs a struct in C++?

The differences between a class and a struct in C++ is:

  • struct members and base classes/structs are public by default.
  • class members and base classes/struts are private by default.

Both classes and structs can have a mixture of public, protected and private members, can use inheritance and can have member functions.

I would recommend you:

  • use struct for plain-old-data structures without any class-like features;
  • use class when you make use of features such as private or protected members, non-default constructors and operators, etc.

When will I use a Class Variable in Java v.s an Instance Variable?

My personal understanding of a class variable is that a single copy of a class variable that has been declared in a class will be declared using the keyword static, and that each object that has been instantiated from the class will contain a single copy of the class variable.

No. It's not that "each object will contain a single copy". A static variable is associated with the type rather than each instance of the type. The instances don't have the variable at all.

There's exactly one variable (assuming you're only loading it from one classloader) however many instances of the type there are. No instances? Still one variable. A million instances? Still one variable.

Static variables are mostly useful for constants or constant-alikes - things like loggers, or "the set of valid prices" etc. Things which don't change over the course of the application. They should almost always be final in my experience, and the type should be an immutable type (like String). Where possible, use immutable collections too for static variables - or make sure the variable is private and that you never mutate the collection within the class.

You should avoid using static variables to store global changing state. It makes code much harder to test and reason about.



Related Topics



Leave a reply



Submit