澳门皇冠金沙网站-澳门皇冠844网站

热门关键词: 澳门皇冠金沙网站,澳门皇冠844网站

面向对象皇冠国际娱乐中心,方法和接口

文章由作者马志国在博客园的原创,若转载请于明显处标记出处:

 文章由作者马志国在博客园的原创,若转载请于明显处标记出处:

类型系统

类型系统是指一个语言的类型体系结构。一个典型的类型系统通常包含以下内容:

  • 基础类型:byte int bool ...
  • 复合类型:数组 结构体 指针 ...
  • 可以指向任意对象的类型(Any类型)
  • 值语义和引用语义
  • 面向对象的特征 如成员方法
  • 接口

类型系统描述的是这些内容在一个语言中如何被关联。

皇冠国际娱乐中心,以java举例,在Java中存在两套完全独立的类型系统:一套是值类型系统,主要是基本数据类型(int byte char 等 ),这些类型是值语义的。另一套则是以Object为根的对象类型,这些类型可以定义成员变量和成员方法。java中的Any类型就是Object,值类型想要被Object引用需要装箱(int->Integer)。

相比之下Go语言的大多数类型都是值语义,并且都可以包含对应的操作方法。在需要的时候可以给任何类型添加新方法。而在实现某个接口时,无需从该接口继续(Go不支持继承),只要实现该接口要求的所有方法即可。GO语言的Any类型就是空接口interface(),可以引用任何类型。

皇冠官网手机版网址,Go学习群:415660935

结构体是由一系列具有相同类型或不同类型的数据构成的数据集合。这些数据称为结构体的成员。Go语言的结构体和其他语言的类有同等的地位,但Go语言放弃了包括继承在内的大量面向对象特性,只保留了组合这个最基础的特性。这也体现了Go语言的简洁性。这章内容主要实现了Go语言的面向对象编程。

结构体(struct)是由一系列具有相同类型或不同类型的数据构成的数据集合。这些数据称为结构体的成员。Go语言的结构体和其他语言的类有同等的地位,但Go语言放弃了包括继承在内的大量面向对象特性,只保留了组合这个最基础的特性。这也体现了Go语言的简洁性。这章内容主要实现了Go语言的面向对象编程。

为类型添加方法

例1:

package main

import "fmt"

type Integer int

func (a Integer) Less(b Integer) bool  {
    return a<b
}

func main()  {
    var a Integer =1
    if a.Less(2){
        fmt.Println(a,"less 2")
    }
}


运行结果:
1 less 2

Process finished with exit code 0

皇冠国际平台,例1 定义了一个新类型Integer,我们为其新增了一个Less方法。

例2:

package main
import "fmt"
type Integer int

func (a *Integer) Add(b Integer) {
    *a  = b
}

func main()  {
    var a Integer =1
    a.Add(2)
    fmt.Println(a)
}

Go语言中的面向对象最为直观,如果要求对象必须以指针传递,这有时会是个额外成本,有时对象很小,用指针传递并不划算。
只有在你需要修改对象的时候,才必须使用指针,比如例2
如果你写成这样

func (a *nteger) Add(b Integer) {
    a  = b
}

那么你得打的值仍然会是1,而不是3。因为go语言类型都是属于值传递,要想修改变量的值,只能传递指针。

6.1.1 结构体定义

定义一个结构体相当于定义了一个新的类型。定义结构体的一般形式:

type类型名称struct{

成员列表

}

例如,定义一个类型Person

typePersonstruct{

namestring

ageint

}

另外需要注意的是,结构体成员的输入顺序也有重要的意义。如果成员的顺序不同,意味着定义了不同的结构体类型。一个命令为S的结构体类型将不能再包含S类型的成员,因为一个聚合的值不能包含它自身(该限制同样适应于数组)但是S类型的结构体可以包含*S指针类型的成员,这可以创建递归的数据结构,例如链表和树结构。如果结构体没有任何成员的话,就是空结构体,写作struct{}.它的大小为0,也不包含任何信息。

6.1.1 结构体定义

定义一个结构体相当于定义了一个新的类型。定义结构体的一般形式:

type 类型名称 struct {

   成员列表

}

   例如,定义一个类型Person

type Person struct {

  name string

  age  int

}

另外需要注意的是,结构体成员的输入顺序也有重要的意义。如果成员的顺序不同,意味着定义了不同的结构体类型。一个命令为S的结构体类型将不能再包含S类型的成员,因为一个聚合的值不能包含它自身(该限制同样适应于数组)但是S类型的结构体可以包含*S指针类型的成员,这可以创建递归的数据结构,例如链表和树结构。如果结构体没有任何成员的话,就是空结构体,写作struct{}.它的大小为0,也不包含任何信息。

值语义和引用语义

值语义和引用语义的差别在于赋值
b = a
b.Modify()
如果b的修改不会影响a,属于值类型,如果影响属于引用类型。

Go语言中大多数属于值类型,包括:

  • 基本类型 int bool 等
  • 复合类型 array 结构体struct 指针

Go语言中有4个类型比较特别,看起来像引用类型

  • 数组切片:指向数组的一个区间
  • map:极其常见的数据类型
  • channel:执行体间的通信设施
  • 接口:对一组满足某个契约的类型的抽象

6.1.2结构体初始化

结构体变量的的初始化可以按顺序直接初始化,也可以按照字段:值的方式初始化,这种方式的初始化对于字段的初始化的顺序可以是任意的。另外,也可以先定义结构体变量,随后赋值。

p1:=Person{"张三",20}//1 按顺序初始化

fmt.Println

p2:=Person{age:18,name:"李四"}//2采用字段:值的方式初始化,可以任意顺序

fmt.Println

p3:=Person{}//3 未显示初始化,其成员默认被初始化为零值

fmt.Println

p3.name="王五"//给每个成员赋值

p3.age=19

fmt.Println

6.1.2结构体初始化

结构体变量的的初始化可以按顺序直接初始化,也可以按照字段:值的方式初始化,这种方式的初始化对于字段的初始化的顺序可以是任意的。另外,也可以先定义结构体变量,随后赋值。

p1 := Person{"张三", 20} // 1 按顺序初始化

fmt.Println(p1)

p2 := Person{age: 18, name: "李四"} // 2采用字段:值的方式初始化,可以任意顺序

fmt.Println(p2)

p3 := Person{}// 3 未显示初始化,其成员默认被初始化为零值

fmt.Println(p3)

p3.name = "王五" //给每个成员赋值

p3.age = 19

fmt.Println(p3)

结构体

Go 语言的结构体(struct)和其他语言的类(class)有同等地位,但Go放弃了包括继承在内的大量的面向对象的特性,只保留了组合这个最基础的特性。

定义一个矩形类型,再定义Area成员方法来计算面积

type Rect struct {
    x, y float64
    width, hight float64
}

func (rect *Rect)Area() float64 {
    return rect.hight*rect.width
}

6.1.3 匿名组合实现继承

1 匿名组合的实现

只声明一个成员对应的数据类型而不指明成员的名字,这类成员就叫匿名成员。通过匿名成员实现的匿名组合,可以完成继承的功能。下面定义一个Student类,继承Person类的功能。匿名组合类型相当于以其类型名称作为成员变量的名字。

typePersonstruct{

namestring

ageint

}

typeStudentstruct{

Person

majorstring

}

funcmain(){

s1:=Student{Person{"张三",18},"计算机应用"}

fmt.Println

fmt.Println(s1.Person)

fmt.Println("姓名:",s1.Person.name,"年龄:",s1.Person.age,

"专业:",s1.major)

fmt.Println("姓名:",s1.name,"年龄:",s1.age,"专业:",s1.major)

}

//打印结果:

{{张三 18} 计算机应用}

{张三 18}

姓名: 张三 年龄: 18 专业: 计算机应用

姓名: 张三 年龄: 18 专业: 计算机应用

2匿名组合的重名问题

以下的示例中,Base1、Base2和Child名称相同。另外,匿名组合中Base2使用了指针类型。

typeBase1struct{

namestring

}

typeBase2struct{

namestring

}

typeChildstruct{

Base1

*Base2

namestring

}

funcmain(){

c:=Child{Base1{"base1"},&Base2{"base2"},"child"}

fmt.Println

fmt.Println

fmt.Println(c.Base1.name)

fmt.Println(c.Base2.name)

}

//打印结果:

{{base1} 0xc0420082c0 child}

child

base1

base2

6.1.3 匿名组合实现继承

1 匿名组合的实现

只声明一个成员对应的数据类型而不指明成员的名字,这类成员就叫匿名成员。通过匿名成员实现的匿名组合,可以完成继承的功能。下面定义一个Student类,继承Person类的功能。匿名组合类型相当于以其类型名称(去掉包名部分)作为成员变量的名字。 

 

type Person struct {

    name string

    age  int

}

type Student struct {

    Person

    major string

}

 

func main() {

  s1 := Student{Person{"张三", 18}, "计算机应用"}

  fmt.Println(s1)

  fmt.Println(s1.Person)

  fmt.Println("姓名:", s1.Person.name, "年龄:", s1.Person.age, 

"专业:", s1.major)

  fmt.Println("姓名:", s1.name, "年龄:", s1.age, "专业:", s1.major)

}

//打印结果:

{{张三 18} 计算机应用}

{张三 18}

姓名: 张三 年龄: 18 专业: 计算机应用

姓名: 张三 年龄: 18 专业: 计算机应用

 

 

2匿名组合的重名问题 

以下的示例中,Base1、Base2和Child名称相同。另外,匿名组合中Base2使用了指针类型。

type Base1 struct {

    name string

}

type Base2 struct {

    name string

}

type Child struct {

    Base1

    *Base2

    name string

}

 

func main() {

    c := Child{Base1{"base1"}, &Base2{"base2"}, "child"}

    fmt.Println(c)

    fmt.Println(c.name)

    fmt.Println(c.Base1.name)

    fmt.Println(c.Base2.name)

}

 

//打印结果:

{{base1} 0xc0420082c0 child}

child

base1

base2

初始化

定义好了Rect,可以有以下几种方式初始化:

rect1 := new(Rect)
rect2 :=&Rect{0,0,100,100}
rect3 :=&Rect{width:100,hight:100}
rect4 :=&Rect{}

Go语言没有构函数,使用一个全局的创建函数new来创建

6.1.4 匿名结构

funcmain(){

a:=&struct{

Namestring

Ageint

}{

Name:"zhangsan",

Age:18,

}

fmt.Println

b:=struct{}{}

fmt.Println

}

//打印结果:

&{zhangsan 18}

{}

6.1.4 匿名结构

func main() {

  a := &struct {

      Name string

      Age  int

  }{

      Name: "zhangsan",

      Age:  18,

  }

  fmt.Println(a)

  b := struct{}{}

  fmt.Println(b)

}

//打印结果:

&{zhangsan 18}

{}

匿名组合

确切的说,Go语言也提供了继承,但是采用了组合的文法,我们称之为匿名组合

type Base struct {
    Name string
}

func (base *Base)Foo()  {
}
func (base *Base)Bar()  {
}

type Foo struct {
    Base
}

func (foo *Foo) Bar() {
    foo.Base.Bar()
}

以上代码定义了一个Base类,实现了Foo()和Bar(),然后定义了一个Foo类,该类从Base类“继承”并改写了Bar()

本文由澳门皇冠金沙网站发布于编辑程序,转载请注明出处:面向对象皇冠国际娱乐中心,方法和接口