面向对象的三个基本特征?
面向对象编程(OOP)是一种编程范式,它使用“对象”来设计应用程序和计算机程序。它利用了几个核心概念,其中三个基本特征是封装、继承和多态。
封装(Encapsulation)
封装是OOP的一个核心概念,它是指将对象的数据(属性)和操作这些数据的方法(行为)捆绑在一起,形成一个独立的实体。这样做的目的是隐藏内部的复杂性,只向外部提供一个可以被访问的接口。通过封装,对象的内部工作原理可以被隐藏起来,只暴露必要的操作,这样可以减少系统的复杂性,提高安全性。
继承(Inheritance)
继承是从一个已存在的类创建新类的过程,新创建的类称为“子类”,已存在的类称为“父类”。子类继承了父类的属性和方法,可以添加新的属性和方法,也可以重写父类的方法。继承支持代码复用,使得子类可以扩展父类的功能。
多态(Polymorphism)
多态是指允许不同类的对象对同一消息做出响应的能力,即同一个接口可以被不同的对象以不同的方式实现。这意味着编写的代码可以对不同类型的对象进行操作,即使每个对象的具体实现细节不同,也可以调用相同的方法。
聊聊Go的结构体与方法
Go语言中没有“类”的概念,也不支持“类”的继承等面向对象的概念。
但是当我们想表达一个事物的全部或部分属性时,这时候再用单一的基本数据类型明显就无法满足需求了,Go语言提供了一种自定义数据类型,可以封装多个基本数据类型,这种数据类型叫结构体。
Go语言中通过struct来实现面向对象。Go语言中通过结构体的内嵌再配合接口比面向对象具有更高的扩展性和灵活性。
Go语言中的方法就是一个包含了接受者的函数,接受者可以是命名类型或者结构体类型的一个值或者是一个指针,所有给定类型的方法属于该类型的方法集,下面是一个方法的定义:
func (recevier type) methodName(参数列表)(返回值列表){}
Go语言的接口是怎么实现的?
Go语言的接口通过一种叫做接口类型(interface type)机制实现的。在Go语言中,接口是一种抽象类型,它定义了一组方法,但是这些方没有具体实现。具体的实现由实现了这些接口的类型来提供,有几个关键点:
- 接口是一组方法的集合。
- 任何类型只要实现了接口类型中的所有方法,就被认为实现了该接口。
- 接口类型本身也是一种类型,可以用来声明变量。
- 接口变量可以保存任何实现接口的类型的值。
具体实现方式:
package main
import (
"fmt"
)
type Speaker interface {
Speaker() string
}
type Person struct {
name string
}
func (p Person) Speak() string {
return "Hello,my name is" + p.name
}
func main() {
var s Speaker
person := Person{name:"John"}
s = person
fmt.Println(s.Speak())
}
接口内部的实现原理?
接口在Go语言中的实现是基于接口类型的内部结构实现的,通常包含两个主要字段:动态类型和动态值。 接口变量持有一个具体的类型和该类型的值的指针,这样接口就支持动态转型,也称为类型断言。动态类型和动态值的组合决定了接口也引用的是什么对象以及该对象的值。
Go的组合与继承的区别?
继承的问题
继承是面向对象编程中的一个核心概念,它允许我们定义一个类(子类)来继承另一个类(父类)的特性。然而,继承也带来了一些问题。
首先,过度使用继承会导致代码结构复杂化,这会使代码的维护和理解变得困难。例如,深层次的继承树和多重继承都可能引发问题。
其次,继承违反了封装原则,因为子类可以访问父类的保护字段和方法。这种紧密耦合使得修改父类的代码变得困难,因为这可能会影响到子类的行为。
最后,继承通常是在编译时确定的,这限制了程序的灵活性。例如,我们不能在运行时改变一个对象的类。
组合的优点
相对于继承,组合提供了一个更为灵活、强大的代码复用机制。组合模型中,一个对象(称为复合对象)可以包含另一个对象(称为组件对象),复合对象可以使用组件对象的行为。
这种模式的优点在于:
- 模块化:每个组件对象都是独立的,它只需要关注自己的行为。这使得代码更容易理解和维护。
- 灵活性:我们可以在运行时动态地改变复合对象的行为,只需要替换其组件对象即可。
- 避免深层次的继承关系:使用组合,我们可以更容易地重用代码,而无需创建复杂的类层次结构。
- 更好的封装:复合对象只能通过组件对象的公共接口来访问其行为,这保证了组件对象内部状态的封装性。
Go语言中的组合
在Go语言中,我们可以通过嵌入(embedding)来实现组合。嵌入允许我们将一个类型(通常是结构体)包含在另一个类型中,而无需创建新的字段。被嵌入的类型的方法会自动“提升”到包含它的类型上,就像这些方法是直接定义在包含类型上一样。
Go语言中如何用interface实现多态?
关键在于定义一个接口类型,并且由多个不同的类型可以实现这个接口。然后,使用接口类型的变量,动态的调用实现类的方法,就可以实现多态。
package main
import (
"fmt"
)
type Animal interface {
Speak() string
}
type Dog struct{}
func (d Dog) Speak() string {
return "Woof"
}
type Cat struct{}
func (c Cat) Speak() string {
return "Meow"
}
func main() {
animals := []Animal{Dog{},Cat{}}
}
在上面例子中,我们定义了一个Animal接口和两个实现这个接口类型的Dog和Cat,通过遍历[]Animal切片,我们能够调用不同类型的Speak方法,这便是多态。