随便写点技术性的文章
golang是一门google设计的类C语言,它是用于替代Python的语言. 它更C,更面向过程,而并不C++,并不那么面向对象. 但是,我还是想实现类似于C++中的接口,事实上,它是能够做到的,虽然写法比较C.
单一继承简单来说就是只有一个父类,具体实现起来我又做了两种实验:
在C++里面伪代码实现为:
typedef struct interface;
interface IFruit {
virtual string GetName() const = 0;
virtual void SetName(string name) = 0;
virtual Type GetType() const = 0;
};
class Apple : public IFruit {
public:
virtual string GetName() const {}
virtual void SetName(string name) {}
virtual Type GetType() const {}
};
在golang里面的实现大概是这样的:
我们先定义一个接口:
type Fruit interface {
GetName() string
SetName(name string)
GetType() Type
}
我们有一根香蕉:
type Banana struct {
name string
energy float32
}
func NewBanana(name string) *Banana {
c := &Banana{}
c.name = name
c.energy = 0
return c
}
func (c *Banana) GetName() string {
return c.name
}
func (c *Banana) SetName(name string) {
c.name = name
}
func (c *Banana) GetType() Type {
return BananaType
}
func (c *Banana) SetEnergy(energy float32) {
c.energy = energy
}
func (c *Banana) GetEnergy() float32 {
return c.energy
}
我们这里有一个NewBanana用于创建新的香蕉,而这个方法可以有两种用法:
var fruitBanana Fruit
fruitBanana = NewBanana("big")
banana := NewBanana("little")
还可以用基类提供的工厂方法NewFruit来创造水果:
apple := NewFruit(AppleType, "big")
banana := NewFruit(BananaType, "big")
在C++里面伪代码实现为:
typedef struct interface;
interface IVehicle {
virtual string GetName() const = 0;
virtual void SetName(string name) = 0;
virtual Type GetType() const = 0;
virtual void SetWheelCount(wheelCount int) = 0;
virtual int GetWheelCount() const = 0;
virtual string ToString() const = 0;
};
class VehicleBase: public IVehicle {
virtual string ToString() const {}
};
class Apple : public VehicleBase {
public:
virtual string GetName() const {}
virtual void SetName(string name) {}
virtual Type GetType() const {}
virtual void SetWheelCount(wheelCount int) {}
virtual int GetWheelCount() const {}
virtual string ToString() const {}
};
在golang里面的实现大概是这样的:
我们先定义一个接口:
type Vehicle interface {
GetType() Type
GetName() string
SetName(name string)
SetWheelCount(wheelCount int)
GetWheelCount() int
ToString() string
}
再来一个基类:
type vehicleImpl struct {
wheelCount int
}
func (c *vehicleImpl) SetWheelCount(wheelCount int) {
c.wheelCount = wheelCount
}
func (c *vehicleImpl) GetWheelCount() int {
return c.wheelCount
}
func (c *vehicleImpl) ToString() string {
return "vehicle -> "
}
那么接着咱来俩公交车:
type Bus struct {
vehicleImpl
name string
}
对的,它组合了基类vehicleImpl
.
在这里公交车把基类的ToString()
给覆盖了,但是我们可以这样调用c.vehicleImpl.ToString()
:
func (c *Bus) ToString() string {
str := fmt.Sprintf("Bus -> %s", c.GetName())
return c.vehicleImpl.ToString() + str
}
多重继承就是具有多个父类.
在C++里面伪代码实现为:
class Father {
virtual string GetName() const {}
virtual string Say() const {}
};
class Mother {
virtual string GetName() const {}
virtual string Say() const {}
};
class Child : public Father, public Mother {
virtual string GetName() const {}
virtual string Say() const {
Father::GetName();
Mother::GetName();
}
};
我们先整一个爸爸:
type Father struct {
}
func NewFather() Father {
c := Father{}
return c
}
func (c *Father) GetName() string {
return "Tony"
}
func (c *Father) Say() string {
return "I am " + c.GetName()
}
我们先整一个妈妈:
type Mother struct {
}
func NewMother() Mother {
c := Mother{}
return c
}
func (c *Mother) GetName() string {
return "Aurora"
}
func (c *Mother) Say() string {
return "I am " + c.GetName()
}
我们先整一个爸爸妈妈的继承者:
type Child struct {
*Mother
Father
}
func NewChild() Child {
c := Child{}
return c
}
func (c *Child) GetName() string {
return "Jerry"
}
func (c *Child) Say() string {
return "I am " + c.GetName() + ", My Father is " + c.Father.Say() + ", My Mother is " + c.Mother.Say() + "."
}
其实也没啥,关键就是在于匿名成员*Mother
和Father
.
在这里,继承方式有两种:
- 在派生类没有改写基类的成员方法时,相应的成员方法被继承。
- 派生类可以直接调用基类的成员方法,譬如基类有个成员方法为Base.Func(),那么Derived.Func()等同于Derived.Base.Func()
- 倘若派生类的成员方法名与基类的成员方法名相同,那么基类方法将被覆盖或叫隐藏,譬如基类和派生类都有成员方法Func(),那么Derived.Func()将只能调用派生类的Func()方法,如果要调用基类版本,可以通过Derived.Base.Func()来调用。
- 基类采用指针方式的组合,依然具有派生的效果,只是派生类创建实例的时候需要外部提供一个基类实例的指针。
- 其他规则与非指针方式组合一致。