“Interfaces” and “Abstract Classes” are features in many object oriented programming languages, but there isn’t an agreement across languages on exactly how they work. A language can not have these features and still be considered “object oriented”, and often different languages will give them different names.
So there are no strict definitions about what these terms mean. But there are general concepts that you can look for.
An “interface” is a description of what a type needs to be able to do, without any definition for how to do it. A common analogy is to think about the controls for a machine. You can see and touch the controls of the machine and you can know what the controls do - how they make the machine behave. But you don’t necessarily need to know anything about how the machine actually does the things the controls tell it to do. You can imagine keeping the same controls but upgrading the machine to a newer model - the insides of the machine all changed, but how you control the machine stays the same.
In OOP this usually means defining a type with just method signatures with no method bodies. In Java or C#, you use the interface
keyword for this, in C++ there is no keyword but you can define “pure virtual” classes where all the methods don’t have implementations.
An “abstract type” or “abstract class” is a class where some of the methods don’t have definitions. Say you create a class with 5 methods, and you write the function bodies for 3 of the methods but leave the other 2 undefined. This creates a class that “has a hole in it”. A lot of the class is filled in, but there are parts left deliberately empty so they can be filled in in multiple different ways. It lets you write a class where you know some behaviors are always going to be the same, but specific parts will need to be different. You then “plug in” different versions of the abstract parts by creating different subclasses. In Java you use the abstract
keyword for this, in C++ the virtual
keyword.
There are many use cases for both of these patterns, and I would encourage you to search around online for examples (I think even Wikipedia can have good ones).
Now you might have noticed that I didn’t mention Python at all so far.
This is because Python is one of those programming languages that doesn’t have either interfaces or abstract classes, at least not in the way Java, C++, or C# do.
- Python is interpreted, not compiled. In those other languages, you need to explicitly write down your interfaces and abstract types so that the compiler can make sure that all the parts of your program fit together correctly.
- Python is dynamically typed, not statically typed. In the other example languages, when you declare a variable you have to tell the compiler what type of value is going to be stored in that variable, and from then on in your program that is the only kind of value that you can put in that variable. Then the compiler checks all the places you assign variables and call methods to make sure that all the usages match their declarations. If a method says it takes a single string parameter, you can’t pass it an integer instead. In Python, variables don’t have a declared type. Values have types, but variables in Python are just names. You can name a value that happens to be a string, then later use that same name to refer to a number instead. You can write a function and say it takes one argument, but that argument could really be any kind of value. (You usually document what kinds of values you support, or check for them inside the function.)
- Perhaps most importantly, Python’s object system is “duck typed”. What this means in practice is that when running a Python program, the interpreter doesn’t care what the class of an object is. Instead, it only requires that the object has the attributes you ask for. When you have some object named
foo
, and you write foo.myvalue
, the interpreter basically just asks foo
: “hello, do you have an attribute called “myvalue
”? And if it does, then it gives it to you, and if it doesn’t, you get an error. Nowhere does the interpreter ask “foo” what type it is, or what class it was created from, or what other attributes and methods it has - it just tries to get the one attribute you asked for. And it does this every time you ask for any property or method of any object.
There are ways that you can use the object system to emulate things like abstract classes. (There’s even a nice standard library module for it.) They don’t work exactly like a Java abstract class, because Python fundamentally works differently than Java - things that Java does when compiling a program, Python either does not do at all (on purpose!) or checks while the program is running instead. But it can be a nice way to document things for other programmers and to check for mistakes when your program is running.
Python also has a system of type annotations, but that would be another long post so I won’t go there for now, haha.