From http://www.vaikan.com/program-to-an-interface-fool/
For ' interface ' programming, not for ' implementation '.
What does that mean?
First we need to understand what is ' interface ' and what is ' implementation '. In short, an interface is a collection of the series of methods that we want to invoke, with objects that respond to these method calls.
An implementation is where code and logic are stored for the interface.
Essentially, this principle advocates that when we write a function or a method, we should refer to the corresponding interface instead of the specific implementation class.
programming for ' implementation '
First, let's see what happens if we don't follow this principle.
Suppose you are the "Montag" in the book "Fahrenheit 451". As we all know, the book will burn at 451 degrees Fahrenheit. The fire fighters in the novel will throw them into the fire as long as they see the book. We use object-oriented perspective to say the problem, the book has a burn()
method called.
Books are not the only things that burn. Suppose we have another thing, like Wood, and it has a method called burn()
. We write this code in the rust language to see how they burn in situations where programming is not oriented to ' interface '.
structBook{ title:@str, author:@str,}structLog{ wood_type:@str,}
Very direct. We created two structures to represent a book and a wood (log). Here's how we implement them for structs:
Impl Log { fn Burn(& Self) { println(FMT!("The%s log is burning!", Self.Wood_type)); }}Impl Book { fn Burn(& Self) { println(FMT!("The book '%s by%s ' is burning!", Self.title, Self.author)); }}
Now Log
and Book
all have a burn()
way, let's put them on the fire.
We first put the wood on the fire:
fn Start_fire(LG: Log) { LG.Burn();}fn Main() { Let LG = Log { Wood_type: @"Oak", length: 1, }; //Burn the Oak log! Start_fire(LG);}
Very smoothly, we got the output "the Oak log is burning!".
Now, because we have written a start_fire
function, whether we can pass the book in, because they all have burn()
. Let's try it:
fnmain(){ letbook=Book{ title:@"The Brothers Karamazov", author:@"Fyodor Dostoevsky", }; // Let‘s try to burn the book... start_fire(book);}
Is it possible? no way. The following error has occurred:
Mismatched types:expected but Log
found Book
(expected struct logs but
Found struct book)
That's very clear, because the function we write requires a Log
struct, not the structure we passed in Book
. How to solve this problem? We can write one more way to change the parameters into Book
structures. However, this is not a good plan. I have two almost the same function in two places, and if one changes, we need to remember to modify the other one.
Now let's see how programming for ' interface ' can solve this problem.
interface-Oriented programming
We still use the previous structure, but this time we add an interface. In the rust language, the interface is called traits:
struct book Span class= "P" >{
title : @ str author : @ str } struct log { wood_type : @ str } trait burnable { Span class= "K" >fn burn ( & self
Now, in addition to the two structures, we have another called Burnable
interface. There is only one method called in its definition burn()
. Let's implement their interfaces for each struct:
Impl burnable for Log { fn Burn(& Self) { println(FMT!("The%s log is burning!", Self.Wood_type)); }}Impl burnable for Book { fn Burn(& Self) { println(FMT!("The book\"%s\"By %s was burning! ", Self.title, Self.author)); }}
It doesn't seem to change much. This is where interface-oriented programming is powerful:
fnstart_fire<T:Burnable>(item:T){ item.burn();}
More than just receiving a book object or log object for parameters, we can pass in any type that implements the Burnable
interface (we call it type T
). This allows our main function to be written like this:
fn Main() { Let LG = Log { Wood_type: @"Oak", }; Let Book = Book { title: @"The Karamazov", author: @"Fyodor Dostoevsky", }; //Burn the Oak log! Start_fire(LG); //Burn the book! Start_fire( Book);}
As expected, we get the following output:
The Oak log is burning!
The book "The Karamazov" by Fyodor Dostoevsky is burning!
This is exactly the same as we expected.
Conclusion
Following the "interface-oriented" programming principle, we can write a function that allows it to fully reuse any object that implements the Burnable
interface. Because many programmers are charged hourly, the more reusable code we write, the less time it takes to maintain them, which is better.
Therefore, this is a very powerful programming idea.
It's not always possible to interface-oriented programming, but following this principle makes it easier to write more elegant code that can be reused. The interface provides a very good abstraction and makes our development work much easier.
For "interface" programming and for "implementation" programming