面向对象的四大特性
- 抽象—数据抽象(属性)和过程抽象(方法)
- 封装—限定对外方法,控制数据访问
- 继承—数据共享、代码重用
- 多态—派生对象就是父对象
c++ 抽象和封装
#include <iostream>
using namespace std;
class rect {
private:
int length; //长度
int width; //宽度
public:
int area(){
return length*width;
}
rect(int length, int width){
this->length = length;
this->width = width;
}
};
int main()
{
rect c(10, 10);
cout<<"area:"<<c.area()<<"\n";
// area:100
}
go 抽象和封装
package main
import "fmt"
// 结构体:长方形
type rect struct {
length int // 长度
weight int // 高度
}
// 方法:长方形面积
func (r *rect) area() int {
return r.length * r.weight
}
// go属性和方法的可见性是包(package)级别
// 如果,将属性名和方法名定义为大写字母开头
// 那么,对其他包(package)可见
func main() {
// go没有构造函数
r := rect{10, 10}
fmt.Println("area:", r.area())
// area: 100
}
go方法(传值和传址)
package main
import "fmt"
// 结构体:长方形
type rect struct {
length int // 长度
width int // 宽度
}
// 方法:增加长度(传值)
func (r rect) increase_length_value() {
r.length = r.length + 1
}
// 方法:增加长度(传址)
func (r *rect) increase_length_pointer() {
r.length = r.length + 1
}
// 方法:长方形面积
func (r rect) area() int {
return r.length * r.width
}
// 传值:对象副本
// 传址:对象地址
// 1、是否修改对象
// 2、对象副本创建成本
func main(){
r := rect{length:10, width:10}
fmt.Println("area:", r.area())
// area: 100
r.increase_length_value()
fmt.Println("area:", r.area())
// area: 100
r.increase_length_pointer()
fmt.Println("area:", r.area())
// area: 110
p := &rect{length:10, width:10}
fmt.Println("area:", p.area())
// area: 100
p.increase_length_value()
fmt.Println("area:", p.area())
// area: 100
p.increase_length_pointer()
fmt.Println("area:", p.area())
//area: 110
//可用实例value和pointer调用全部方
//编译器自动转换
}
c++ 继承
#include <iostream>
using namespace std;
class rect {
private:
int length; //长度
int width; //宽度
public:
int area(){
return length*width;
}
rect(int length, int width){
this->length = length;
this->width = width;
}
};
class cube : public rect{
private:
int height; //长度
public:
cube(int length, int width, int height)
:rect(length, width) {
this->height = height;
}
int volume(){
return this->area() * this->height;
}
}
int main()
{
cube c(10, 10,10);
cout<<"area:"<<c.volume()<<"\n";
// area:1000
}
go “继承”
package main
import "fmt"
// 结构体:长方形
type rect struct {
length int // 长度
width int // 高度
}
// 方法:长方形面积
func (r *rect) area() int {
return r.length * r.width
}
type cube struct {
rect //匿名属性
height int //长度
}
func (r *cube) volume() int {
return r.area() * r.height
}
func main() {
c := cube{rect{10, 10}, 10}
fmt.Println("area:", c.volume())
}
// 编译器负责查找匿名方法,实现类似继承的复用
c++(is-a)
#include <iostream>
using namespace std;
class rect {
private:
int length; //长度
int width; //宽度
public:
int area(){
return length*width;
}
rect(int length, int width){
this->length = length;
this->width = width;
}
};
class cube : public rect{
private:
int height; //长度
public:
cube(int length, int width, int height)
:rect(length, width) {
this->height = height;
}
int volume(){
return this->area() * this->height;
}
};
void print_area(rect r) {
cout<<"area is:" << r.area()<<"\n";
}
int main()
{
rect r(10, 10);
print_area(r);
// area:100
cube c(10, 10,10);
print_area(c);
// area:100
}
go(has-a)
package main
import "fmt"
// 结构体:长方形
type rect struct {
length int // 长度
width int // 高度
}
type cube struct {
rect //匿名属性
height int //长度
}
// 方法:长方形面积
func print_area(r rect) {
fmt.Println("area:",r.length * r.width)
}
func main() {
r := rect{10, 10}
print_area(r)
//area: 100
//c := cube{rect{10, 10}, 10}
//print_area(c)
// cannot use c (type cube) as type rect
// in argument to print_area
}
// 真正的多态,派生对象就是父对象
go(fake-is-a)
package main
import "fmt"
// 结构体:长方形
type rect struct {
length int // 长度
width int // 高度
}
// 方法:长方形面积
func (r *rect) area() int {
return r.length * r.width
}
type cube struct {
rect //匿名属性
height int //长度
}
func main() {
c := cube{rect{10, 10}, 10}
fmt.Println("area:", c.area())
//area: 100
}
// 编译器负责查找匿名方法
// 实现类似继承的复用能力
c++(多重继承——属性重复)
#include <iostream>
using namespace std;
class plane {
public:
int length; //共同属性
int width;
};
class line {
public:
int length; //共同属性
string name;
};
class combile:public plane, public line{
};
int main()
{
combile c;
c.name = "my name";
//c.length = 10;
//member 'length' found in multiple
//base classes of different types
plane *p;
p = &c;
p->length = 10;
cout<<p->length<<"\n";
//10
line *l;
l = &c;
l->length = 5;
cout<<l->length<<"\n";
//5
return 0;
}
// is-a
go(多重复合——属性重复)
package main
import "fmt"
// 平面
type plane struct{
length int //长度
width int //宽度
}
// 直线
type line struct {
length int // 长度
name string // 名称
}
type combine struct {
line
plane
}
func main() {
l := line{50, "first line"}
p := plane{10,10}
c := combine{l, p}
fmt.Println("length of c1:", c.name)
fmt.Println("length of c1:", c.width)
fmt.Println("length of c1:", c.line.length)
fmt.Println("length of c1:", c.plane.length)
//fmt.Println("length of c1:", c.length)
//ambiguous selector c.length
}
//has-a
go(is-a)
package main
import "fmt"
type flyer interface {
fly()
}
type bee struct {
name string
}
type plane struct{
name string
}
func (b *bird) fly() {
fmt.Printf("%s is flying \n", b.name)
}
func (p *plane) fly() {
fmt.Printf("%s is flying \n", p.name)
}
func i_can_fly(f flyer){
fmt.Println("i can fly")
f.fly()
}
func main() {
b := bee{"first bee"}
i_can_fly(&b)
// i can fly
// first bee is flying
p := plane{"BY 737"}
i_can_fly(&p)
// i can fly
// BY 737 is flying
}
//接口是一个或多个方法签名的集合。
//任何类型的方法集中只要拥有该接口'对应的全部方法'签名。
//就表示它 "实现" 了该接口,无须在该类型上显式声明实现了哪个接口。
//接口只有方法声明,没有实现,没有数据字段。
//接口命名习惯以 er 结尾。
// go把struct作为数据和逻辑的结合
// 通过组合(composition),has-a关系来最小化代码重用
// go使用接口interface来建立(type)之间的is-a关系
go interface自动判断
package main
import "fmt"
type flyer interface {
fly()
}
type spider struct {
}
func (s *spider) fly() {
fmt.Println("spider can fly!")
}
type hero interface {
save_world()
}
type looser struct {
}
func (l *looser) save_world() {
fmt.Println("i'm a looser ,
but i can save the world!")
}
type spider_man struct {
spider
looser
}
type super_man interface {
fly()
save_world()
}
func welcome_superman(s super_man) {
s.save_world()
s.fly()
fmt.Println("welcome the superman!")
}
func main() {
s := spider{}
l := looser{}
sp := spider_man{s, l}
welcome_superman(&sp)
// i'm a looser ,but i can save the world!
// spider can fly!
// welcome the superman!
}
c++ interface显示判断
#include <iostream>
using namespace std;
class flyer {
public:
virtual void fly() = 0;
};
class hero {
public:
virtual void save_world() = 0;
};
class super_man {
public:
virtual void fly() = 0;
virtual void save_world() = 0;
};
class spider_man : public flyer, public hero {
public:
void fly(){
cout<<"i can fly!\n";
}
void save_world(){
cout<<"i can save world!\n";
}
};
class captain: public super_man {
public:
void fly(){
cout<<"i can fly!\n";
}
void save_world(){
cout<<"i can save world!\n";
}
};
void welcome_superman(super_man &s){
s.fly();
s.save_world();
cout<<"welcome the superman!";
}
int main()
{
//spider_man s;
//welcome_superman(s);
// note: candidate function not viable:
// no known conversion from 'spider_man'
// to 'super_man &'
captain c;
welcome_superman(c);
//i can fly!
//i can save world!
//welcome the superman!
return 0;
}
go interface{}
package main
import "fmt"
// 结构体:长方形
type rect struct {
length int // 长度
width int // 高度
}
func print_filter(i interface{}){
fmt.Println("nogo print:", i)
}
func main() {
i := 10
s := "nogo"
r := rect{10, 10}
print_filter(i)
//nogo print: 10
print_filter(s)
//nogo print: nogo
print_filter(r)
//nogo print: {10 10}
}
参考文章:
https://blog.youkuaiyun.com/li_101357/article/details/80205005
https://blog.youkuaiyun.com/zhangjg_blog/article/details/18790965