1024programmer Java Understanding of language interfaces in C, C, and golang

Understanding of language interfaces in C, C, and golang

I have only used C and C before, and I only have a logical understanding of the concept of interface. I think it is a channel that connects code writers and users. Now I have come into contact with GO language, interface { }) is an important feature of GO, so we decided to sort out and compare the interface features of C, C and GO.

C Language

The interface concept of C language is relatively simple. When only the basic usage of C language is discussed (without simulation of object-oriented usage) Below, the coupling between its interface and the user is the highest. If the user wants to call a certain piece of functional code, he usually needs to obtain the interface type by including the header file. Interface users do not need to care about the specific implementation of the interface. As long as the interface remains unchanged (the part in the header file), we can freely modify the interface implementation code. C is an emotional sharp knife. It provides you with a very specific method. The method of use is single and the scalability is poor (It seems a bit off topic… But let’s discuss it again. Please understand the difference between process-oriented and object-oriented). For example, we now need to implement a program that uses different tools to peel different foods:

#include 
//Interface
typedef struct apple { //apple
//
const char* name;
int size;
}apple;
typedef struct nut { //nut
//
const char* name;
int size;
}nut;
typedef struct hammer {
const char* name;
int power; //Strength
int sharpness ; //Sharpness
}hammer;
typedef struct knife {
const char* name;
int power;
int sharpness;
}knife;
void peelApple_hammer( apple* tar, hammer* tool){
if(!tar || !tool){
return;
}
if (tool->sharpness == 0){
printf( "Peel %s by %s Failed.\n", tar->name, tool->name);
return;
}
printf("Peel %s with %s. take %d seconds .\n", tar->name, tool->name, tar->size/tool->sharpness);
return;
}
void peelApple_knife(apple* tar, knife* tool){
if(!tar || !tool){
return;
}
if (tool->sharpness == 0){
printf("Peel %s by %s Failed. \n", tar->name, tool->name);
return;
}
printf("Peel %s with %s. take %d seconds.\n", tar->name , tool->name, tar->size/tool->sharpness);
return;
}
void peelNut_hammer(nut* tar, hammer* tool){
if(!tar || !tool){
return;
}
if (tool->power == 0){
printf("Peel %s by %s Failed.\n", tar->name, tool->name);
return;
}
printf("Peel %s with %s. take %d seconds.\n", tar->name, tool->name, tar-> size/tool->power);
return;
}
void peelNut_knife(nut* tar, knife* tool){
if(!tar || !tool){
return;
}
if (tool->power == 0){
printf("Peel %s by %s Failed.\n", tar->name, tool->name);
return;
}
printf("Peel %s with %s. take %d seconds.\n", tar->name, tool->name, tar->size/tool->power);
return;
}
External program
int main(){
struct apple strap = {"Apple", 10};
struct nut strnut = {"Nut", 5} ;
struct hammer strham = {"hammer", 5, 0};
struct knife strkni = {"knife", 1, 5};
peelApple_hammer(&strap, &strham);
peelApple_knife( &strap, &strkni);
peelNut_hammer(&strnut, &strham);
peelNut_knife(&strnut, &strkni);
return 0;
}

Print:

Peel Apple by hammer Failed.
Peel Apple with knife. take 2 seconds.
Peel Nut with hammer. take 1 seconds.
Peel Nut with knife. take 5 seconds.

At this point, if we want to add a fruit or a peeling tool, we need to add at least one data type and 1*n (the number of current types of fruit or tools) functions interface.

C

The interface of C can be called an abstract class, that is, setting an abstract base class to describe an Group basic behaviors (interfaces), and then complete the interface through diverse derived classes. The interface exists as a contract between different components, and the implementation of the contract is mandatory, that is, the language must declare that it implements the interface.

#include 
class fruit;
interface
class toolsak {
public:
toolsak(const char* na, int pow , int shar){
name = na;
power = pow;
sharpness = shar;
}
const char* name;
int power;
int sharpness;
};
class fruit {
public:
fruit(const char* na, int siz){
name = na;
size = siz;
}
const char* name;
int size;
public:
virtual void peel(toolsak* tool) = 0;
};
class hammer : public toolsak {
public:
hammer(const char* name, int power, int sharp):toolsak(name, power, sharp){}
};
class knife : public toolsak {
public:
knife(const char* name, int power, int sharp):toolsak(name, power, sharp){}
};
class apple : public fruit {
public:
apple(const char* name, int size):fruit(name, size){}
void peel(toolsak* tool){
if(!tool || tool->sharpness == 0){
return;
}
printf("Peel the %s with %s. take %d seconds\n", name, tool->name, size/tool->sharpness);
}
};
class nut : public fruit {
public:
nut(const char* name, int size):fruit(name, size){}
void peel(toolsak* tool) {
if(!tool || tool->power == 0){
return;
}
printf("Peel the %s with %s. take %d seconds\n", name, tool->name, size/tool->power);
}
};
External program
int main(){
toolsak* tptr = new hammer("hammer" , 5, 0);
fruit* fptr = new apple("apple", 10);
toolsak* tptr2 = new knife("knife", 1, 5);
fruit* fptr2 = new nut("nut", 5);
fptr->peel(tptr);
fptr->peel(tptr2);
fptr2->peel(tptr);
fptr2->peel( tptr2);
return 0;
}

Print:

Peel the apple with knife. take 2 seconds
Peel the nut with hammer. take 1 seconds
Peel the nut with knife. take 5 seconds

golang

There is no need for a hard connection between the implementation class and the abstract interface (that is, declaring inheritance or virtual functions). As long as your implementation class implements the methods specified by an interface, then the user of the class can instantiate the class and assign it to interface, and then specific methods can be called directly through the interface.

package main
import (
"errors"
"fmt"
)
type tool struct {
name string
power int
sharpness int
}
type fruit struct {
name string
size int
}
type toolIf interface {
getName() string
getPower() int
getSharpness() int
}
type fruitIf interface {
peel(too interface{toolIf}) error
}
type hammer struct {
*tool
}
type knife struct {
*tool
}
type apple struct {
*fruit
}
type nut struct {
*fruit
}
func (a *apple) peel(too interface {toolIf}) error {
if too.getSharpness() == 0 {
return errors.New("xxxx")
}
//do that
fmt.Printf("Peel the %v with %v, take %v seconds\n", a.name, too.getName(), a.size/too.getSharpness())
return nil
}
func (n *nut) peel(too interface{toolIf}) error {
if too.getPower() == 0 {
return errors.New("xxxx" )
}
//do that
fmt.Printf("Peel the %v with %v, take %v seconds\n", n.name, too.getName(), n.size/ too.getPower())
return nil
}
func (t *tool) getName() string {
return t.name
}
func (t *tool) getPower () int {
return t.power
}
func (t *tool) getSharpness() int {
return t.sharpness
}
func main() {
var (
appFr fruitIf = &apple{&fruit{"apple", 10}}
appNu fruitIf = &nut{&fruit{"nut", 5}}
toolHam = &hammer{&tool{"hammer", 5, 0}}
toolKni = &knife{&tool{"knife", 1, 5}}
)
appFr.peel(toolHam)
appFr.peel(toolKni)
appNu. peel(toolHam)
appNu.peel(toolKni)
return
}

Print:

Peel the apple with knife,  take 2 seconds
Peel the nut with hammer, take 1 seconds
Peel the nut with knife, take 5 seconds

Tips: It should be noted that in GO language, use examples It is best to use pointers instead of objects themselves when assigning values ​​to interfaces, otherwise compilation errors may be reported: because you can define methods for a certain type or type pointer, such as:

type fruitIf interface {
getsize() error
getname() error
}
type apple struct{}
func (a apple) getsize() error {
return nil
}
func (a *apple) getname() error {
return nil
}
func main () {
//var appl apple
var frIf fruitIf = &apple{}
frIf. getsize()
}

The above code can be compiled because Go can automatically generate a new method based on function 1⃣:

func (  a *apple)getsize() error {
return *a.getsize()
}

Obviously, GO automatically encapsulates it for us, but not vice versa:

ttype fruitIf interface {
getsize() error
}
type apple struct{}
func (a apple) getsize() error {
return nil
}
func (a *apple) getname() error {
return nil
}
func main () {
var appl apple
var frIf fruitIf = appl
frIf.getsize()
}

This cannot be compiled because GO cannot generate the following new methods for you based on the object:

func (a apple)getname()error {
return &a.getname()
}

Because all GO function parameters are passed by value, do Operations cannot affect external real objects.

Summary

An interface is a specification, a protocol, an abstracted method set, simply the word itself In terms of meaning, the above-mentioned languages ​​are not superior. Even if they are object-oriented and process-oriented, “interfaces that can withstand changes in requirements” require programming languages ​​​​to have more reasonable interface designs. In this category, I personally think : Although the interface of C language is the simplest, it is easier to understand because of its lower scalability at the language level. However, if the interface needs to be extended, it will be an extremely painful process; C is greatly improved through inheritance and virtual functions. The scalability of the interface is improved, and the code is concise and clear, provided that explicit declaration is required; Go directly supports the design of interfaces at the language level, and the process of using interfaces is greatly simplified. If one of your classes fully implements the method set, then you are equivalent to implementing the interface, even if the definition process of the two is not related, this is the so-called “non-intrusive interface”. The meaning needs to be understood slowly~

An interface is a specification, a protocol, and an abstracted method set. In terms of the meaning of its own words, the above-mentioned languages ​​​​are not superior. Even if they have differences between object-oriented and process-oriented, “can” “Interface that can withstand changes in demand” requires programming languages ​​​​to have more reasonable interface designs. In this category, I personally think that although the C language interface is the simplest, it is easier to understand because of its lower scalability at the language level. However, if you need to extend the interface, then this will be an extremely painful process; C greatly improves the scalability of the interface through inheritance and virtual functions, and the code is concise and clear, provided that it needs to be explicitly declared; Go directly supports interfaces at the language level The process of designing and using interfaces is greatly simplified. If one of your classes completely implements the method set in an interface, then you are equivalent to implementing the interface, even if the definition process of the two is not related. This is So-called “non-intrusive interface”. The meaning needs to be understood slowly~

This article is from the internet and does not represent1024programmerPosition, please indicate the source when reprinting:https://www.1024programmer.com/understanding-of-language-interfaces-in-c-c-and-golang/

author: admin

Previous article
Next article

Leave a Reply

Your email address will not be published. Required fields are marked *

Contact Us

Contact us

181-3619-1160

Online consultation: QQ交谈

E-mail: [email protected]

Working hours: Monday to Friday, 9:00-17:30, holidays off

Follow wechat
Scan wechat and follow us

Scan wechat and follow us

Follow Weibo
Back to top
首页
微信
电话
搜索