Go - 31 Go 面向对象编程思想-抽象/封装/继承

面向对象编程三大特性
    Golang任然有面向对象编程的继承,封装和多态的特性,只是实现的方式和其他OOP语言不一样;
 
如何理解抽象?(研究问题的方法或者编程思想)
    我之前定义一个结构体的时候,实际上就是把一类事物的共有的属性(字段)和行为(方法)提取出来,形成一个物理模型(模板),这种研究问题的方法称为抽象;
 
封装
    封装(encapsulation)就是把抽象出的字段和对字段的操作封装在一起,数据被保护在内部,程序的其他包只有通过被授权的操作(方法),才能对字段进行操作。
    封装的理解和好处
        1.隐藏实现细节;
        2.可以对数据进行验证,保证安全合理(Age设置是否合理);
    如何体现封装
        1.对结构体中的属性进行封装;
        2.通过方法,包,实现封装;
    封装实现的步骤:
        1.将结构体,字段(属性)的首字母小写(不能导出了,其他包不能使用,类似private);
        2.给结构体所在包提供一个工厂模式的函数,首字母大写,类似一个构造函数
        3.提供一个首字母大写的Set方法(类似其他语言的public),用于对属性判断并赋值
            func 
        4.提供一个首字母大写的Get方法(类似其他语言的public),用于获取属性的值;
        特别说明:
            在Golang开发中并没有特别强调封装,这点并不像java/python等,Golang本身对面向对象的特性做了简化的;
        案例:例如创建一个Person结构体,不能随便查看人的年龄,工资等隐私,并对输入的年龄及逆行合理的验证;
        实现:创建一个文件夹(包): model (person.go)  main(main.go)
        model/person.go
        package model 
        import "fmt" 
        type person struct {     
            Name string      
            age  int      
            sla  float64 
        } 
         // 结构体首字母小写,需要工厂模式的函数 相当于构造函数         
        func NewPerson (name string) *person {     
            return &person{         
                    Name: name,     
                } 
        } 
         // 为了访问age 和sla 我们编写一对Setxxx的方法和Getxxx的方法 
        func (p *person) SetAge(age int) {     
            if age > 0 && age < 150 {         
                p.age = age      
            }else {         
                fmt.Println("年龄设置不合法...") // 可以给默认值     
            } 
        } 
    func (p *person) GetAge() int {     
        return p.age 
    } 
     // sla 
    func (p *person) SetSla(sla float64) {     
        if sla >= 3000.0 && sla <= 30000 {         
            p.sla = sla      
        }else {         
            fmt.Println("薪水范围不靠谱...")     
        } 
    } 
    func (p *person) GetSla() float64 {     
        return p.sla  
    }
 
    调用: main/main.go
    package main 
    import (     
        "fmt"     
        . "go_study_file/encapsulation_study/model" 
    ) 
    func main() {     
        p := NewPerson("tom")     
        fmt.Println(*p)  // {tom 0 0}     
        p.SetAge(27)     
        p.SetSla(17000)     
        fmt.Println("姓名==",p.Name, "年龄==", p.GetAge(), "薪水===", p.GetSla())  // 姓名== tom 年龄== 27 薪水=== 17000
    }
    
 
继承
    为什么需要继承?
    为了防止代码冗余,利于代码维护,功能的扩展---继承的方法(代码复用性高);
    继承基本介绍和基本语法:
    在结构体中嵌入一个匿名结构体,即实现继承的特性;
    当多个结构体存在相同的属性(字段)和方法时,可以从这些结构体中抽象出结构体,在该结构体中定义这些相同的属性和方法。
    其他的结构体不需要重新定义这些属性(字段)和方法,只需嵌套一个匿名结构体即可;
    也就是说:在Golang中,如果一个struct嵌套了另一个匿名结构体,那么这个结构体可以直接访问匿名结构体的字段和方法,从而实现了继承特性;
 
继承的深入讨论
    1.结构体可以使用嵌套匿名结构体所有的字段和方法,即,首字母大写或者小写的字段/方法都可以使用;
    2.匿名结构体字段/方法 访问可以简化;
    3.当结构体和匿名结构体有相同的字段或者方法时,编译器采用就近访问原则访问,如希望访问匿名结构体的字段和方法,可以通过匿名结构体名来区分;
    4.结构体嵌入两个(或多个)匿名结构体,如两个匿名结构体有相同的字段和方法(同时结构体本身没有同名的字段和方法),在访问时,就必须明确指定匿名结构体名字,否则编译报错。
    5.如果一个struct嵌套了一个有名结构体(stu Student),这种模式就是组合,如果是组合关系,那么在访问组合的结构体的字段或方法时,必须带上结构体的名字;
    6.嵌套匿名结构体后,也可以在创建结构体变量(实例)时,直接指定各个匿名结构体字段的值。
    7注意:    
        1.如果一个结构体有int类型的匿名字段,就不能有第二个;
        2.如果需要有多个int的字段,则必须给int字段指定名字;
        3.
 
多重继承-说明
    如果一个struct嵌套了多个匿名结构体,那么该结构体可以直接访问嵌套的匿名结构体的字段和方法,从而实现了多重继承。
    细节注意:
        1.如嵌入的匿名结构体有相同的字段或者方法名,则在访问时,需要通过匿名结构体名来区分。
        2.为了保证代码的简洁性,建议大家尽量不使用多重继承;
 
 
 
 
    
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
posted @ 2020-12-19 12:45  以赛亚  阅读(260)  评论(0编辑  收藏  举报