面向过程和面向对象思考

最近在学习go,go里没有class,像C一样是面向过程的。但是实际上也能实现封装,继承,多态这三个面向对象核心思想。回想起平时工作中的代码,虽然是用java写的,但大部分写的其实都是和面向过程的代码。回想起以前看过的一篇公众号文章,略有感悟。

封装,继承,多态

kotlin例子

open class Person(
    open val name: String,
    open val age: Int
) {
    open fun work(): String {
        return "do something..."
    }
}

class Teacher(
    override val name: String,
    override val age: Int,
    val school: String
) : Person(name, age) {

    override fun work(): String {
        return "teaching at $school"
    }
}

class Student(
    override val name: String,
    override val age: Int,
    val school: String
) : Person(name, age) {

    override fun work(): String {
        return "learning at $school"
    }
}

fun main() {
    val li: Person = Teacher("li", 30, "yu cheng high school")
    val wong: Person = Student("wong", 18, "yu cheng high school")
    work(li) // li work: teaching at yu cheng high school
    work(wong) // wong work: learning at yu cheng high school
}

fun work(person: Person) {
    println("${person.name} work: ${person.work()}")
}

封装:Person类封装了name,age属性和work方法
继承:Teacher和Student类继承了Person,并扩展了school属性。重载了work方法
多态:${person.work()}根据不同的类,有不同的行为

一个很简单的例子,还是体现了封装,继承,多态思想。kotlin作为面向对象语言实现起来还是很轻松容易的。

go例子

type Person struct {
    name string
    age  int
}

type Worker interface {
    work() string
}

func (p Person) work() string {
    return "do something..."
}

type Teacher struct {
    Person
    school string
}

func (t Teacher) work() string {
    return fmt.Sprintf("teaching at %v", t.school)
}

type Student struct {
    Person
    school string
}

func (t Student) work() string {
    return fmt.Sprintf("learning at %v", t.school)
}

func main() {
    li := Teacher{Person: Person{name: "li", age: 30}, school: "yu cheng high school"}
    wong := Student{Person: Person{name: "wong", age: 18}, school: "yu cheng high school"}
    work(li) // worker: teaching at yu cheng high school
    work(wong) // worker: learning at yu cheng high school
}

func work(worker Worker) {
    fmt.Printf("worker: %v\n", worker.work())
}

封装:Person struct封装了name,age属性。(p Person) work()封装了work方法
继承:go没有继承,但是可以通过组合来实现。
多态:通过Worker interface接口作为多态扩展

go作为一门面向过程语言,虽然实现面向对象不如其他面向对象语言那么容易,毕竟没有直接的相关概念,但也的的确确能实现,而且个人认为也直指本质。

  • 封装说白了其实就是数据结构+行为函数,其他面向对象语言用一个关键字整合了一下罢了。
  • 继承事实上劣于组合,平时工作中也提倡组合优先于继承。
  • 多态本质上其实是函数指针,运行时执行指针指向的具体函数罢了。

指针

以前大一刚开始学习编程的时候,入门就是C语言,相信很多同学都是从C开始的。指针是C语言的精华,但是以前一直不理解,只知道指针本质就是内存地址,但是作用啥的,一直理解不了。而且java里也没指针,所以后来一直没有思考过这个问题。

在学习go的过程中,官网教程里有一段代码

type Vertex struct {
    X, Y float64
}

func (v Vertex) Abs() float64 {
    return math.Sqrt(v.X*v.X + v.Y*v.Y)
}

func (v *Vertex) Scale(f float64) {
    v.X = v.X * f
    v.Y = v.Y * f
}

func main() {
    v := Vertex{3, 4}
    v.Scale(10)
    fmt.Println(v.Abs())
}
type Vertex struct {
    X, Y float64
}

func Abs(v Vertex) float64 {
    return math.Sqrt(v.X*v.X + v.Y*v.Y)
}

func Scale(v *Vertex, f float64) {
    v.X = v.X * f
    v.Y = v.Y * f
}

func main() {
    v := Vertex{3, 4}
    Scale(&v, 10)
    fmt.Println(Abs(v))
}

v.Scale(10) 看起来很像面向对象的风格对吧,instance.method()。但是呢,实际上这个和Scale(&v, 10)本质上是一样的。如果把指针v换一下,换成SELF,那么看起来是不是和python一样了。如果语言支持隐式的SELF,那么写起来是不是就和java一样。所以,java class里的方法,其实都隐含了一个指向自己的SELF指针,或者叫做this,所以java其实也是有指针的。

总结

以前有个leader说过一句"名言":重要的是思想。一门语言是面向过程还是面向对象其实并不重要。面向过程语言也能写得和面向对象一样,而面向对象语言 ,如果不理解面向对象思想的话,写出来的代码还是和面向过程一样的。

你可能感兴趣的:(面向过程和面向对象思考)