服务热线:13616026886

技术文档 欢迎使用技术文档,我们为你提供从新手到专业开发者的所有资源,你也可以通过它日益精进

位置:首页 > 技术文档 > JAVA > 新手入门 > 基础入门 > 查看文档

我的thinking in java学习笔记(十)


  第六章 重复运用classes
在面向过程的语言中重复运用代码只是简单的复制代码,以达到重复运用的目的,而在面向对象的java程序中,代码的重用主要体现在2点
1、在新的class中使用既有的class,这中方法称之为"组合"。但是这种重用方式只是很单纯的重复运用以有的代码 功能,而非重复运用其形式。
2、让新的class成为既有class的一类,并且根据需要加入新的功能,而无须更动原有class,这种方法称之为"继承"。
组合语法
其实组合我们在以前的例子中已经大量的用到了,我们只要将对象句柄放置在class中就是组合!
class compostion
{
private string s;
compostion()
{
system.out.println("compostion()");
s=new string("hello");
}
public string tostring()
{
return s;
}
}
public class test
{
compostion c; //对象句柄
int i;
public void show()
{
system.out.println("int = "+i);
system.out.println("compostion = "+c);
}
public static void main(string args[])
{
test t = new test();
t.show();
}
}
其中每个非基本数据类型的对象都有一个tostring()方法,该函数用于将compostion转换为一个string,和其他string相加class中基本数据类型会被初始化为默认值,而对象句柄会被初始化为null。如果你要使用该句柄,切记要初始化,否则会抱空指针错误!
继承
继承是java语言中极其重要的一部分,使用关键字extends来实现,这样变自动的让子类获得了父类中所有的成员数据和函数。而java中所有的类甚至包括你自己已经定义的或者将要定义的类都是继承自object类的,在编译器内部进行的隐式继承
class base
{
int i=10;
public void show()
{
system.out.println("base method");
}
public static void main(string args[]) // java允许在同一个文件中的class拥有各自的main()
{
new base().show();
}
}
class derived extends base //继承
{
public void show() //覆盖了base的函数
{
system.out.println("derived method");
super.show(); //调用base的函数
}
public void newmethod() //子类中新加入的函数
{
system.out.println(i); //打印base中的数据
}
public static void main(string args[])
{
derived d = new derived();
d.show();
d.newmethod();
}
}
base的初始化
当子类被初始化的时候系统会先将被继承的父类初始化,java编译器会在调用子类构造函数之前调用父类的构造函数
class base
{
base()
{
system.out.println("base method");
}

}
class derived extends base
{
derived()
{
//super(); 系统会自动加入对父类的调用
system.out.println("derived method");
}
public static void main(string args[])
{
derived d = new derived();
}
}
假如你的父类是带有引数的class,那么编译器是不会自动调用构造函数的,你必须使用super来调用,否则系统会抱错
class base
{
base(string s)
{
system.out.println(s);
}

}
class derived extends base
{
derived()
{
super("base method"); //必须是构造函数的第一行语句
system.out.println("derived method");
}
public static void main(string args[])
{
derived d = new derived();
}
}
兼容组合和继承
有的时候,我们在编写class的时候不但用到组合,还用到继承。
组合和继承之间的选择
如果你只是希望在新class中使用到既有class的功能,并且隐藏起实现细目,那么最好使用组合。
如果你希望为既有的class开发一种特殊版本,那么继承再好不过了。
如果你的既有类和新类是一种is a的(是一个)关系,那么使用继承,如果是一种has a(有一个)关系,那么使用组合
protected
我们再来复习一下protexted的意义:继承此class的子类,可以访问该类的成员,并且对于一个包内的其他类是friendly的
渐进式开发
继承的优点之一就是支持渐进式开发,在这种开发模式下,你可以在程序中加如新的程序代码,但是却不影响父类的代码
向上转型
由于继承的关系,在子类中可以使用父类的所有函数,并且任何发送给父类的消息,也可以发送给子类
class base
{
protected void show()
{
system.out.println("base method");
}
protected void getsomeone( base b)
{
b.show();
}
}
class derived extends base
{
public static void main(string args[])
{
derived d = new derived();
d.getsomeone(d);
}
}
注意在getsomeone的函数定义中,我们定义的是他只能接受一个base类的句柄,然而他居然接受了子类的句柄。因为子类虽然和父类不太相同,但是他毕竟是父类的一种因此适用与父类的函数当然也适用与子类咯,我们把这种把子类转型为父类的做法叫做向上转型upcasting
class base
{
public void methodone()
{
system.out.println("base.methodone");
}
public void methodtwo()
{
system.out.println("base.methodtwo");
}
}

class derived extends base
{
public void methodone()
{
system.out.println("derived.methodone");
}
public void methodtwo()
{
system.out.println("derived.methodtwo");
}
public void methodnew()
{
system.out.println("derived.methodnew");
}
public static void main(string[] args)
{
base d = new derived();
d.methodone(); //虽然已经向上转型成为了base,但是调用的函数还是基类的函数,显示derived.methodone
d.methodtwo(); //同上
//d.methodnew(); 因为已经向上转型,所以丢失了子类特有的函数
}
}
为什么需要向上转型?
子类是父类的一个超集,因此子类中至少包含父类中的函数,并且可能会更多。然而向上转型会使子类遗失和父类不同的方法,向上转型一定是安全的,因为这是从特殊类型改变成通用类型。
组合vs继承
当你需要向上转型的时候是使用继承的最佳时间
关键字final
什么是final?就是"最终"的意思,也就是不可改变的意思,我们在这里讨论3中final:data、method、class
final data
final的数据是固定不变的,不变的数据称之为常量,他是很有用的,因为它
1、可以是永不改变的编译期常量。编译期常量可以在编译期执行某些计算,减少执行期的负担,此类常量必须是基本数据类型,使用final修饰,必须给定初值。
2、可以在执行期被初始化,而你却不想再改变他。
如果某个数据既有static还有final,那么他就会拥有一块无法改变的储存空间。当把final用于对象时,final让句柄保持不变不能再重新指向其他对象,然而对象本身却是可以改变的,这点和final的基本数据类型不能改变其值的特点有所不同。
class value
{
int i = 1;
}
class finaldata
{
//编译期常量
final int i = 10;
static final int ii = 20;
//典型的常量
public static final int iii= 30;
//执行期常量
final int iiii = (int)(math.random()*20);
static final int iiiii = (int)(math.random()*20);

value v = new value();
final value vv =new value();
static final value vvv =new value();
//数组
final int[] a = { 1,2,3,4,5,6};

扫描关注微信公众号