面向过程的结构化编程,例如1972年美国贝尔研究所推出的C语言,这类编程方式重点放在在定函数上,将较大任务分解成若干小任务,每个小任务由函数实现,分而治之的思想,然而随着软件规模的不断扩张,软件的复杂程度空前提高,例如Vista系统代码达到5000万行,安装光盘有2.5GB。这种情况下,面向过程的自顶向下按功能将软件分解成不同模块的开发方式,分解模块时很难保持各模块的独立性,使程序员设计模块时很难排除其他模块的影响,要同时考虑众多模块,故随着程序规模的扩大,需要记住的细节越来越多,到一定程序时就变得难以应付了。另外,数据与代码相分离的情况下,程序员往往很难理清数据和操作之间的联系。从而出现了软件危机。面向对象编程(Object-Oriented Programming,OOP)面向对象编程(Object-Oriented Programming,OOP)是一种强有力的软件开发方法,在这种方法中,数据和对数据的操作被封装成“零件”,人们用这些零件组装程序。面向对象编程的组织方式和人们认识现实世界的方式一致,符合人们的思维习惯,大大减轻程序员的思维负担;同时它有助于控制软件的复杂性,提高软件的生产效率。所以面向对象方法得到广泛应用,已成为目前最流行的软件开发方法。20世纪80年代初,贝尔实验室在C语言基础上设计了C++语句,1995年Sun公司提出了Java语言,2000年微软公布了C#语言。

  面向对象编程和结构化编程并不矛盾,实际上面向对象编程的局部就是由结构化程序单元组成的。

1.面向对象的基本概念

主要有类、封装、接口和对象等。

类,每一类事物都有特定的属性和行为,这些不同属性和行为将各类事物区别开来,面向对象编程采用类的概念,将事物编写成一个个的类,用数据表示事物的属性,用函数实现事物的行为。

封装,正如开车的无需知晓汽车内部结构和原理,它们已被汽车工程师封装在汽车内部,仅需利用提供给司机的一个简单使用接口,司机操纵方向盘和各种按钮就可以灵活自如开动汽车。面向对象技术把事物属性和行为的实现细节封装在类中,形成一个个可重复使用的“零件”,这些“零件”可被成千上万程序员在不必知晓其内部原理情况下使用。这样程序员能够充分利用他人编写好的“零件”,将主要精力集中在自已专门的领域。

接口,人们通过类的接口使用类,程序员在编写类时精心地为其设计接口,既为方便其它程序员使用,也有利于类的升级改造。

对象,类是一个抽象的概念,而对象是类的具体实例,例如人是一个类,李白、杜甫等都是对象。即类是抽象的概念,对象是真实的个体。

2.创建类和对象

使用Class ***{}的方式定义类,未在Class前添加public的类只能在相同命名空间内部使用,为了能够在其它命名空间使用类,要在Class前添加public标志符。类的成员变量称为Field,也即是字段,类的属性用变量表示,类的行为用方法实现。类通过公有成员实现接口,让界可以通过接口使用类的功能。

C#通过new 运算符创建对象,执行该语句时系统先为对象分配相应的内存空间,然后通过类的构造函数初始化类的成员变量(每个类都有一个默认的与类同名的构造函数),这种创建对象的过程叫做类的实例化。如果创建了同一个类的多个对象,则它们共享方法的代码,但不共享数据成员,每个对象都会在内存中开辟新的空间来存储自己的数据成员。C#3.0中加入新特性——对象构造器,使得对象的初始化工作变得格外简单,我们可以采用类似于数组初始化的方式来初始化类的对象。比如:Cat doraemon = new Cat { name = "Doraemon", age = 8 };。

1)属性

用公有方法读写变量不但可以对数据进行合法性检查,而且提高了类的封装性,一箭双雕。这种专门用来读写数据的方法称为访问器(Assessor)访问器虽然解决了变量 age 的访问问题,但是人们还是习惯于把年龄作为一个变量对待,用方法访问不符合人们的思维习惯。

为了解决这个问题,C#设计了一种特殊的语法——属性(Property)。在属性中,定义了get和set两个访问器,get访问器用来读取变量的值,set访问器用来设置变量的值。set访问器没有声明显式参数,但它有一个名为value的隐式参数。属性的运行方式和方法相似,因此属性可以看作特殊的方法,但属性的使用方式和变量完全相同。无论何时使用属性,都会在后台隐式地调用get访问器或set访问器,并执行访问器中的代码。每个属性背后都对应着一个变量,我们一般让属性和它所对应的变量同名,只是将首字母大写,以示区别。比如变量age相对应属性Age。有时候属性很简单,get和set里面只有取值和赋值,没有其它逻辑代码,这种属性可以通过自动属性来快速定义public int Name { get; set;}。这时编译器会自动创建一个与Name属性相关的私有变量(仅将属性名首字母改成小写)以及Name属性的定义代码。总之,自动属性包含两层含义,先创建一个私有变量,然后创建该私有变量的属性。

2)构造函数

创建对象时,系统先为对象的成员变量分配内存,然后通过构造函数(Constructor)初始化对象的成员变量。

构造函数,当未定义构造函数时,编译器会为每个类分配一个默认构造函数,它将未明确赋值的整型字段和字符串字段分别初始化为0和null。通过自定义带参数的构造函数,带参数的构造函数可以把类 的员变量初始化为指定的值。构造函数是一种特殊的函数,它必须和类同名,并且没有返回类型(连void也没有)。当我们自定义了构造函数后,默认构造函数就失效了,要想继续使用无参数的构造函数,必须显式定义。自定义构造函数的函数体也可以为空,这时系统会用默认值初始化类的变量成员。

析构函数和垃圾回收,不用的对象要及时删除以释放内存空间,在传统的面向对象设计中用类的析构函数(Destructor)删除对象。析构函数也与类同名,只是要在函数名前加符号~,它不能带任何参数,也没有返回值。由于定义类时编译器会自动生成一个缺省的析构函数,所以一般情况下没有必要编写析构函数,而且由于C#设计了非常完善的垃圾回收机制,一般也不用向析构函数里添加代码。析构函数通常用来释放对象使用的非托管资源。当对象即将离开作用域时,系统自动调用对象的析构函数,释放对象所占的资源。然而在大型的程序中,有时有些对象虽然不再使用了,但离作用域结束还有相当长的时间,在这期间,对象仍然占用内存,浪费资源。C#专门设计了一套回收资源的机制——垃圾回收器。当垃圾回收器确定某个对象已经无用时,就会自动删除该对象,释放内存空间。在这套机制下,内存自动回收,无需人工干预,解决了常常困扰C++程序员的“内存泄露”问题。总之在C#中删除对象的工作是由垃圾回收器负责完成,析构函数通常用来释放对象使用的非托管资源。

.NET类库已经为我们提供了大量的类,提供了大量现成的“轮子”供我们用,例如DateTime、String等,这样就不用重复地制造了。

3)静态成员

类的静态成员用来描述类的整体特征,静态成员在内存中只有一份,为类的所有对象共享,声明方式:public static int wolvesCount=0;。用 static 关键字修饰的变量称为静态变量,没有用static 关键字修饰的变量称为实例变量,在C#中,实例变量通过对象名引用,而静态变量通过类名引用。

静态方法,一般认为行为是由具体对象发出的,但在某些情况下,对象的概念非常模糊例如Math类,直接通过类名调用方法反而更符合人们思维。因此,可以将类的方法声明静态方法,静态方法用static 关键字声明,调用静态方法时不必事先创立对象,直接通过类名引用。

4)常量成员

类的const常量只能在声明的时候初始化,不能在其它地方赋值,声明方式例如public const double PI=3.1415926;。类的const常量成员是隐式静态的,为所有类对象共有,通过类名来引用,虽然const常量默认静态,但不能用static关键字显式声明。

readonly常量,对于那些在类的具体对象中固定的常数,但在不同对象中可有不同值的变量,通常用readonly常量实现。例如旅店类的房间总数,不同旅店的房间总数不同,但一个旅店的房间总数通常是固定的。一般把readonly常量初始化代码放在了构造函数。

5)重载

C#提供了方法重载的方式,即允许在一个类中定义两个或多个名称完全相同的方法,但要求这些名称相同的方法必须具有不同的参数类型(参数数据类型不同或参数个数不同或同时具有这两点)。方法重载调用原则是参数最佳匹配,即系统调用 参数类型最匹配的那个方法。例如通常在定义类的构造函数时使用方法重载。

重载运算符,重载运算符由关键字operator声明,必须定义为静态。定义方法:pubic static ***(返回类型) operator +(或-*/) (*** z1,***z2){…}。例如:

class Complex

{  public static Complex operator +(Complex z1, Complex z2)

{ return Add(z1, z2);}  …}

6)索引

使用类的索引,可以像访问数组那样访问类的数据成员,定义类索引的方式就像以定义属性的方式定义类的数组成员。例如:

class cube{

private double length;

private double width;

private double height;

public double this[int index]

{

get

{ switch(index)

{ case 0:return length;

case 1:return width;

case 2:return height:

default: throw new IndexOutOfRangeException(“下标出界”);}

}

set{  switch(index)

{case 0: lenth=value;break;

case1 :width=value;break;

case 2:height=value;break;

default: throw new IndexOutOfRangeException(“下标出界”);}

}

}

}

索引的函数体与属性类似,也是用get 和set 访问器。get 访问器用于获取成员变量的值,set 访问器用于为成员变量赋值。索引的使用方法和数组完全一样,如果创建了一个名为 box 的Cube 对象,就可以用box[0],box[1],box[2]分别表示立方体的长、宽、高了。在数组中,下标只能为整数,在索引中,有了更灵活的选择,既可以为 int 型,也可以为double、string 等类型。例如:

class Cube

{

public double this[string indexString]

{

get

{ switch (indexString)

{  case "length": return length;

case "width": return width;

case "height": return height;

//当下标出界时,我们抛出一段异常。

default: throw new IndexOutOfRangeException("下标出界!");}

}

set

{ switch (indexString)

{  case "length": length = value; break;

case "width": width = value; break;

case "height": height = value; break;

default:throw new IndexOutOfRangeException("下标出界!");}

}

}

...

}

C#还为我们提供了多维索引,只需提供多个下标即可,比如Matrix 类中的多维索引public double this[int rowIndex,int columnIndex]这时需要嵌套的switch 语句或双重循环语句等方式来实现。

3.值类型和引用类型

内存中有一块称为栈的区域,用来存储整型、实型、布尔型和字符型等基本类型。操作系统通过栈指针中存储的地址读写栈中的数据,当栈为空时,栈指针指向栈的底部,随着数据的不断入栈,栈指针不断向栈顶部移动,但始终指向栈中下一块自由空间。栈对数据的操作总发生在栈的顶部,最后入栈的变量最先弹出,最先入栈的数据最后弹出,因此先入栈数据的作用域总比后入栈的要长,后入栈数据的作用域嵌套在先入栈数据之中。栈的这种工作方式称为后入先出(Last in first out,LIFO)。整型、实型、布尔型、字符型等简单数据和结构体存储在栈中,称为值类型变量(Value type)。

引用型变量,在类中,我们希望成员变量被构造函数初始化后,即使退出构造函数,这些变量仍然存在,以便在需要的地方使用,为此C#把类的成员变量存储在(Heap)上。内存中创建类的一个对象的过程分两步:

第一步在堆中创建对象:系统在堆中划分一块20 字节的空间用于存储类对象的成员变量,并调用构造函数初始化它们,这样一个对象就被创建了。

第二步在栈上创建引用符:系统在栈中分配4 字节的空间,存储类对象在堆中的首地址。这种存储于栈中的指向堆中对象的地址称为引用符,系统通过引用符找到堆中的对象。

称这种存储在堆上的对象称为引用型变量,引用型变量的垃圾回收机制:在实际程序中,可能会有多个引用符同时指向同一个对象,当某个引用符退出作用域时,系统就会从栈中删除该引用符。当指向对象的所有引用符都被删除时,对象就被加入垃圾回收的候选名单,垃圾回收器会在适当的时候清除该对象。只要存在指向对象的引用符,对象就不会被清除。.Net 使用的是托管堆,托管堆和传统堆不同,当垃圾回收器清除一个对象后,垃圾回收器会移动堆中其他对象,使它们连续的排列在堆的底部,并用一个堆指针指向空闲空间。当创建新对象时,系统根据堆指针可以直接找到自由的内存空间。使用托管堆时创建对象要快很多,虽然删除对象时整理操作会浪费一定的时间,但这些损失会在其它方面得到很好的补偿。声明一个对象的引用符但却未通过new关键字为其创建一个对象时,引用符中存储的只是空地址。注意记住:引用符是对象在内存中的地址。

4.对象的相等、对象数组、匿名类型、扩展方法

1)对象的相等

初次看到Object 类的成员你会感到很惊讶,竟然有三个“相等”函数,如果再加上相等运算符“==”的话,就有4 种进行相等比较的方式了。这些方式之间有什么区别呢?

静态的ReferenceEquals()方法,是一个静态方法,用来测试两个引用符是否指向同一个对象,即两个引用符是否包含相同的内存地址。实例版的Equals()方法,在 Object 类中,实例版Equals()方法是一个虚方法,如果未对其重载,只进行引用比较。但我们一般会在派生类中重写该方法以实现值比较。相等运算符==,。默认状态下,若两个对象为值类型,相等运算符“==”比较两个对象的值;若两个对象为引用类型,相等运算符“==”比较两个引用符。但我们可以通过重载运算符的方法加以改变。静态版 Equals()方法的功能与实例版基本一样,实际上静态版Equals()方法通过调用实例版方法进行比较,只是在调用“objA.Equals(objB)”前,会先检查两个参数是否均为空引用,如果均为空引用,返回true,如果一个为空,一个不为空,返回false。总之,一般情况下,我们让 ReferenceEquals()方法进行引用比较,Equals()方法进行值比较,而相等运算符“==”则看情况而定,如果对象看起来像一个值(比如复数类),就把它设计成值比较,如果对象看起来不像值,就把它设计成引用比较。

2)以对象为元素的数组

例如Cat [] cats=new Cat[5];如此仅是声明了一组引用符而已,并没有真正创建对象。也可以像普通数组那样,声明和初始化同时进行,Cat[] cats = new Cat[]{ new Cat("doraemon,8"), new Cat("Garfield",6) };。

(3)匿名类

有时候某些类在程序中只会使用一次,单独为它编写一个类显得过于啰嗦,这时候用匿名类型就会简洁很多,例如var city = new { Name = "Beijing", ZipCode = 100000 };匿名类型只能由一个或多个公共只读属性组成,不能包含其它种类的类成员。编译时编译器会自动生成相关的类,并创建一个该类的对象以供使用。

(4)扩展方法

很多时候,当需要在已经编译好的类中添加新的功能,但又不想派生该类时,就要以为该类添加扩展方法。

public   static ReturnDataTypeX  ExtensionMethodName(this ExtendedClass x,DataTypeA y,DataTypeB z,…){}

可在任意命名空间的任意一个静态类中为其它类扩展方法,扩展方法的第一个参数类型是想要扩展的类,必须用this关键字修饰,且扩展方法要定义为静态方法。注意调用扩展方法时,只需要引入扩展方法所在的命名空间,通过被扩展类的实例对象,就可以调用这个扩展方法了。

5. 继承

继承(Inheritance)是软件重用的一种形式,采用这种形式,可以在现有类的基础上添加新的功能,从而创造出新的类。

1)由基类创建派生类

例如class Mammal:Vertebrata{},这里Mammal 类由Vertebrata 类派生而出,它不光具有自己的新成员,而且继承了Vertebrata 类的所有成员。派生类Mammal 虽然继承了基类Vertebrata 的所有成员,但出于封装性的考虑,在派生类中不能使用基类的私有成员。

2protected成员

如果想让类的成员既保持封装性又可以在派生类中使用,那么可以把它定义为protected 成员(受保护成员)。总之private 成员只能在定义它的类中使用,既不能被外界使用,也不能被派生类使用;而protected 成员虽然不能被外界使用,但可以被派生类使用。

3)间接继承

例如class Mammal:Vertebrata{}、class Human : Mammal{},那么Human就间接继承了Vertebrata的所有非私有成员。

4)虚方法的重写

考虑到派生类的某些方法虽然与基本同名,但却想赋与其不同的方法内涵,这时就可以把基类的这些方法设计为虚方法,然后在派生类中重写(Override)该方法。虚方法用virtual声明。例如:

class Vertebrata { public virtual void Breathe() { Console.WriteLine("呼吸");}…}

class Mammal : Vertebrata { public override void Breathe() { Console.WriteLine("肺呼吸"); }…}

class Fish : Vertebrata{public override void Breathe(){Console.WriteLine("鳃呼吸");}…}

有三个版本的Breathe()方法,当对象属于Vertebrata 类时,会调用Vertebrata

类中的Breathe()方法;当对象属于Mammal 类时,会调用Mammal 类中的Breathe()方法;当对象属于Fish 类时,会调用Fish 类中的Breathe()方法。总之,系统会根据对象的实际类型调用相应版本的方法。

不但可以重写方法,也可以重写属性,但静态方法不能重写。重写和重载的区别,很多读者一直不清楚方法重载和方法重写的区别,其实重载和重写的区别很简单。重

载是指同一个类中有若干个名称相同但参数不同的方法,调用方法时,系统会根据实参情况,调用参数完全匹配的那个方法。重写是指在继承关系中,在派生类中重写由基类继承来的方法,这时基类和派生类中就有两个同名的方法,系统根据对象的实际类型调用相应版本的方法,当对象类型为基类时,系统调用基类中的方法,当对象类型为派生类时,系统调用派生类中被重写的方法,这其实体现了类的多态性。重载方法发生在同一个类中的同名方法之间,重写方法发生在基类和派生类之间。

5)隐藏基类非virtual的普通方法

由于只能重写基类中的虚方法,不能重写普通方法。要想在派生类中修改基类的普通方法,需要用new 关键字隐藏基类中的方法。例如public new void Sleep(){…},如此可以隐藏父类的同名且非virtual方法。

6base关键字

如何在派生类中调用被重写或隐藏的基类方法呢?我们知道,每个对象都可以用this关键字引用自身的成员,同样,也可以用base关键字引用基类的成员。

7)抽象类和抽象方法

没有实例化意义的类,例如脊椎动物只是一个抽象概念,每一种脊椎动物要么是鱼类,要么是鸟类,要么是哺乳动物等,这样的类可以设计成抽象类,抽象类不能被实例化,只能作为其它类的基类存在,其目的是抽象出子类的公共部分以减少代码重复。抽象类用关键字abstract声明。不光可以声明抽象类,还可以声明抽象方法。抽象方法是一种特殊的虚方法,它只能定义在抽象类中,抽象方法没有任何执行代码必须在派生类中用重写的方式具体实现(如果忘记重写抽象方法的话,会出现编译错误)。除了抽象方法外,我们还可以在抽象类中定义抽象属性(Abstract property)。抽象属性也没有具体实现代码,必须在派生类中重写。

8)密封类和密封方法

密封类(Sealed class)是一种不能被继承的类,用sealed关键字声明。同样,如果想防止一个方法被派生类重写,可以用sealed override关键字把它为声明密封方法,例如public sealed override void F()。

9)派生类的构造函数

创建对象时,系统先调用基类的构造函数,初始化基类的变量,然后调用派生类的构造函数,初始化派生类的变量,是一个由基类向派生类逐步构建的过程。删除对象时,先调用派生类的析构函数,销毁派生类的变量,然后调用基类的析构函数,销毁基类的变量,是一个由派生类向基类逐步销毁的过程。

因为派生类不能使用基类的私有变量,所以不能通过派生类的构造函数直接初始化基类的私有变量,但我们可以通过显式调用基类的构造函数实现。例如:public Human(string nameValue,int ageValue):base(ageValue)。一般情况下尽量用基类的构造函数初始化基类的成员。

10)万类之源Object

C#中所有的类都直接或间接继承于Object 类,C#专门设计了object 关键字,它相当于Object 的别名,该类定义了以下方法:

6.多态性

对象存储在堆中,引用符存储在栈中,引用符的值是对象在堆中的地址,因此通过引用符可以轻松的找到对象,一般情况下,引用符和对象属于同一类型,基类的引用指向基类的对象,派生类的引用指向派生类的对象。基类引用符可以指向派生类对象,但派生类的引用符不能指向基类的对象。继承和多态性是开发复杂软件的关键技术。可以定义基类的引用符,针对此引用符调用基类的某些方法,后续通过不同的派生类对象“赋值”给这个引用符,从而在调用这个基类引用符方法时,使其实际调用派生类对象的不同方法,从而方法的调用呈现多态性。

is引用符,通过它用来判断对象是否与给定的类型兼容(属于该类型或者属于该类型的子类)。所有派生类的对象都可以看作基类的对象。

向上或向下类型转换,由派生类转换为基类,即向上的类型转换是自动进行的,但转换后,基类的引用符不能引用派生类特有的成品。由基类向派生类转换的过程为向下类型转换,这时需要强制向下转换,由于仅当由基类向派生类强制转换才能成功,不然程序就会抛出异常,因此,转换前,应当使用is运算符进行检查,类型是否兼容,强制转换可以通过as运算符实现,例如Vertebrata someone=new Human(); Human people=someone as Human; as转换是执行两个引用类型间的显式转换,是一种安全的转换,使用前不需要使用is运行符测试类型,当类型不兼容时,转换的结果是null,而不会抛出异常,因此通常建议采用as进行类型转换。

7.接口

世界很多组织致力于标准化工作,标准化可以增强产品的通用性,当然也可增强软件的通用性,使软件使用更加方便。在软件领域,实现标准化的一种方法是制定统一的接口(Interface)。接口只规定系统具有哪些成员以及每个成员的功能,具体如何实现由各个公司自己设计,也就是说接口为大家制定了一个规范,然后各公司具体实现这个规范。接口用关键字interface 定义,接口的名称习惯上以字母I 开头。一般情况下,接口中只能包含成员的声明,不能有任何实现代码。接口的成员总是公有的,不需要也不能添加public 等修饰符,也不能声明为虚方法或静态方法。注意,实现接口的类的相应成员必须添加public 修饰,并且可以声明为虚方法。

(1)接口的继承

接口继承方式与类相同,接口跟接口实现类的关系与基类与派生类的关系一样,因此通过使用接口声明对象,也可以很好地使接口声明对象呈现出多态性。

(2)接口的多继承和显式实现

C#中,类与类之间是单继承的,即一个类只能继承一个基类,但类与接口间是多继承的,一个类可以实现多个接口。如果一个类继承了多个接口而这些接口又有重名的成员,就必须用到接口的显式实现,即通过在接口实现类中如此显式实现:

interface IAnimal{ void Breathe();}

interface IPlant{ void Breathe();}

class Life:IAnimal,IPlant

{ void IAnimal.Breathe(){…}

void IPlant.Breathe(){…}}

可以看出,显式实现就在方法属性前加上相应的接口名即可。

C# 篇基础知识3——面向对象编程的更多相关文章

  1. JAVA基础知识之面向对象编程知识汇总

    JAVA基础课程部分面向对象已经学习完成,知识结构如下: 总体知识框架: 类的结构: 面向对象编程三大特征: 关键字和抽象类接口等: 常见知识汇总: 成员变量和局部变量比较 有无返回值方法比较: 权限 ...

  2. Python(三)基础篇之「模块&面向对象编程」

    [笔记]Python(三)基础篇之「模块&面向对象编程」 2016-12-07 ZOE    编程之魅  Python Notes: ★ 如果你是第一次阅读,推荐先浏览:[重要公告]文章更新. ...

  3. [.net 面向对象编程基础] (2) 关于面向对象编程

    [.net 面向对象编程基础]  (2)  关于面向对象编程 首先是,面向对象编程英文 Object-Oriented Programming 简称 OOP 通俗来说,就是 针对对象编程的意思 那么问 ...

  4. JAVA基础知识之网络编程——-网络基础(Java的http get和post请求,多线程下载)

    本文主要介绍java.net下为网络编程提供的一些基础包,InetAddress代表一个IP协议对象,可以用来获取IP地址,Host name之类的信息.URL和URLConnect可以用来访问web ...

  5. Java基础教程:面向对象编程[2]

    Java基础教程:面向对象编程[2] 内容大纲 访问修饰符 四种访问修饰符 Java中,可以使用访问控制符来保护对类.变量.方法和构造方法的访问.Java 支持 4 种不同的访问权限. default ...

  6. Java基础教程:面向对象编程[1]

    Java基础教程:面向对象编程 内容大纲 Java语言概述 Java语言特点 1.Java为纯面向对象的语言,它能够直接反映现实生活中的对象.总之,Everything is object! 2.平台 ...

  7. Java基础教程:面向对象编程[3]

    Java基础教程:面向对象编程[3] 内容大纲 基础编程 获取用户输入 java.util.Scanner 是 Java5 的新特征,我们可以通过 Scanner 类来获取用户的输入.我们可以查看Ja ...

  8. 【转载】[基础知识]【网络编程】TCP/IP

    转自http://mc.dfrobot.com.cn/forum.php?mod=viewthread&tid=27043 [基础知识][网络编程]TCP/IP iooops  胖友们楼主我又 ...

  9. javaSE基础知识(走向编程的门口)— 更新完毕

    前言:玩儿编程最重要的一点:不要怕麻烦,感觉是在浪费时间: 能动手绝不哔哔:只要脑袋不傻,编程都是"一看就会,一练就废",开始学的时候,就算再基础的东西都建议手敲一遍 要有囫囵吞枣 ...

随机推荐

  1. 22 严格模式&this关键词&let&const

    严格模式: ECMA5后的新指令:"use strict" 它不算一条语句,而是一段文字表达式,更早版本的JavaScript会忽略它. 严格模式无法使用未声明的变量. 严格模式的 ...

  2. DC-DC芯片

    KIS-3R33S:同步整流7V-24V转5V/3A DC-DC降压模块 稳压电源模块 效率超过LM2576

  3. 【PAT甲级】1052 Linked List Sorting (25 分)

    题意: 输入一个正整数N(<=100000),和一个链表的头结点地址.接着输入N行,每行包括一个结点的地址,结点存放的值(-1e5~1e5),指向下一个结点的地址.地址由五位包含前导零的正整数组 ...

  4. C/C++网络编程3——地址族与数据序列

    C/C++网络编程2中介绍了套接字,这一节介绍给套接字分配ip和端口号.ip用于标识一台主机,端口号用于标识一个主机中的一个应用程序,端口号占16位,0到65535,其中0到1023是知名端口号. 表 ...

  5. ScrollView不设置contentSize属性依然也可以作为底层滚动View(使用masonry设置scrollView的contentSize)

    第一步 //下层的scroolView self.baseScrollView = [[UIScrollView alloc] init]; self.baseScrollView.delegate ...

  6. 什么是 SDK?

    通俗而言: 1.其实很简单,SDK 就是 Software Development Kit 的缩写,中问意思是: 软件开发工具包. 2.这是一个覆盖面相当广泛的名词,可以这么说: 辅助开发某一类软件的 ...

  7. 一堂优秀学员吕智钊分享----HHR计划----直播课第二课

    备注:本周四:创业者分享,下周四:投资人分享. 08年开始创业. 最重要的两条复盘思考: 大纲: ---坚持最低成本试错,最快速度学习---- 1,复盘1:创业早期如何快速学习 a,从竞争对手身上学习 ...

  8. 【转】issue management in your test project

    What is Issue Management? Issue Management is the process to make others aware of the problem and th ...

  9. 2019年5月17日A股暴跌行情思考

    2019年5月17日A股暴跌行情思考 原因:特朗普针对华为的禁商令,人民币对美元汇率大跌 盘面:平开,单边下跌,收盘80多股跌停 操作:下午2点加仓,满仓 总结: 本次操作太过激进. 局势不明朗时抄底 ...

  10. Spring Boot项目中各配置文件的对比

    application.properties是Spring Boot的全局配置文件,放在src/main/resources目录下或者类路径的/config下,作用是对一些默认配置的配置值进行修改. ...