Java类的继承与多态特性-入门笔记
相信对于继承和多态的概念性我就不在怎么解释啦!不管你是.Net还是Java面向对象编程都是比不缺少一堂课~~Net如此Java亦也有同样的思想成分包含其中。
继承,多态,封装是Java面向对象的3大特征。
继承
如果用.Net写一个A类继承B类的话,写法会是大致如下:
Public Class A : B{ ....... }
Java的话却要通过extends关键字在声明类的时候指定其父类(基类),所以上面的.Net写法要转换成Java的话应该是下面的样子:
Public clas A extends B{ ....... }
我们还是使用一个博客上.Net上继承的列子拿来改成Java的看下效果,下面直接上代码:
现在准备创建一个新类NewCar来继承Car类。
我在向导里指定了包,类的同时我指定了超类(基类/父类)和实现的接口,为了让向导可以生成继承的代码。其结果如下:
突然发现一个偷懒的方法。然后我们在完成剩下的操作,具体代码如下:
运行效果如下:
从这里和.Net的继承对比这里Newcar类虽然没有在类里面定义任何成员变量与成员方法,但是还是从父类继承了它应该拥有的成员。
继承某个父类而生成的新的子类不但拥有父类的变量与方法,还可以为子类添加新的成员变量和新的成员方法,来增强父类的功能,这个就是所谓的扩张。甚至可以在子类中为父类的某些方法定义多个重载方法,这样就增加了这个类的灵活性。Java中子类重写父类的某个方法,方法的申明一定要和父类的方法声明一样。
例如我们上面的继承例子里NewCar中重写父类的drive()方法,具体操作如下:
在Java编辑器中把光标定位在类里面,然后右键选择上面红色框标识的的选项。
选择重写的方法,选择好方法的插入点,然后也勾上添加注释的选项,点击OK如下:
我们的NewCar类中多了一个带这详细注释的方法。在这里的Super关键字的作用就是访问父类的drive()方法,这样我们就不必关心父类drive()方法是如何实现的,然后我们来添加我们新的业务代码及其运行结果如下:
封装
JAVA规范中的设置器与访问器就是实现封装的标准方法,它们用于获取和设置对象的属性值。
1.把属性设置隐藏
要实现封装,开始就要设置类的成员变量使用private修饰符,是其他类无法直接访问该类成员的变量,这样就是防止成员在外面被直接访问和修改。所以我们之前的Car类就可以写成下面:
public class Car{ private String color="黑色"; //颜色 private boolean runing; //形式状态 }
2.定义一个设置器
当我们照上面的做法搞了以后其他类就不能访问了,所以必须通过本类定义一个设置器方法来设置和修改该成员的变量的值。设置器的命名一般以set作为前缀,以属性名作为后缀,如我们写下面一个方法,从名字上你就能理解:
public void SetColor(String color){ this.color = color; //把参数的color赋值给成员color }
3.定义访问器
和设置器一样,因为成员变量被设置成private私有的权限,相对于其他类就隐藏了这个成员变量,所以要使用访问器方法读取对象的属性值。访问器以get或者is作为方法的前缀,以属性名作为后缀,所以我们定义一个如下的访问器:
public String GetColor(){ return color; }
我们从新用封装来从写之前的列子:
在Eclipse里当我们写完私成员后,我们可以利用工具直接生成设置器和访问器,把鼠标放到成员后面如下图操作:
这样工具可以自动生成,不过作为入门新手,还是老老实实打豆豆吧!,具体代码如下:
is和get作为访问器的前缀的用法,主要是为了区分布尔类型和其他类型的属性的访问器。
然后我们写一个实例的类,简单的看来怎么用设置器和访问器,代码如下:
运行结果如下:
附加: Object类
在Java中,所有的类都是直接或者简介的继承了Java.lang.Object类。在.Net所有的类也是从Object类派生的,所以说在.Net还是现在学习的Java Object类算是一个比较特殊的类,他算是所有类的爸爸(父类),就是说在我们创建类的时候没指定继承那个类或者说从某个类派生的话,系统都会默认直接继承Object类,如果指定了继承其他的类,简介的还是继承了object类。
在Java中Object类主要包括clone(),finalize(),equals(),toString()等方法,最常用的是equals()方法和toString()方法;getClass(),notify(),notifyAll(),wait()等方法不能被重写,因为这些方法被定义为final类型。
equals()方法
该方法用于判断两个对象是否为相同的方法,一般子类都会重写该方法,用于比较指定类型的对象;如果没有重新equals()方法,该方法将默认使用“==”运算符判断两个对象。Object类中equals()方法原始定义如下:
public boolean equals(Object obj){ return (this==obj); }
下面演示一个testclass类,默认是继承Object类的实例及运行如下:
可以看出在自定义类中使用equals()方法经行比较时,返回false,因为equals()方法默实现的使用“==”运算符比较两个对象的引用地址,而不是比较对象的内容,所以要比较对象内容的话需要我们重写equals()方法.
toString()方法
toString()方法的功能是将一个对象转换为字符串形式,当一个对象参与字符串的"+"连接操作时,也会调用该方法把对象转换成字符串,然后再和另一个字符串操作连接。toString()方法会返回一个String实例。
下面我们实例一个例子:
我们重写了父类Object中的toString()方法,定义了一句输出的字符串,当我们要输出的时候将自动调用toString()方法。
多态
多态是java是面向对象的三大特征之一,多态程序是指同一种操作在不同环境中有不同的语言解释。例如把子类对象赋值给父类的对象变量如下:
Quadrangle obj = new Square(); //声明父类对象,初始化为子类
声明变量obj是Quandrangle类型的,而赋值时却是Square类型的实例变量。通过使用父类类型的引用,我们就可以定义多态数组或者多态方法。
1.多态数组
多态数组就是数组使用父类声明,而数组中的元素都是子类的实例对象,它们有父类同命的方法,但是方法体却可以不一样。下面来搞一个见简单的实例:
新建一个四边形的类,里面有一个绘制图形的方法,然后分别用长方形,平行四边形,正方形来继承这个四边形的类,然后先实验长方形的类:
,然后继续在写正方形的类继承四边形的类,具体如下:
继续在来写一个平行四边形的类来继承四边形的类,具体如下:
画的不标准,但是不影响我们要去干的事情,现在我们定一个实例类,这个类就来多态数组来使用我们上绘制的三个图形,实例类及运行结果如下:
抽象类于接口
抽象类
在实际问题中,一般将父类定义为抽象类,需要使用这个父类经行继承和多态处理。继承体系中越在上面的类就越抽象,例如说一个动物类等等。。。而在多态机制中,我们并不需要将父类初始化对象,我们需要干的只是了类对象,所以在java中设置抽象类是可以被实例化也存在一定的原油在里面。Java中定义抽象类语法大致如下:
public abstract class Test{ abstract void testAbstract(); //定义抽象方法 }
abstract:字定义抽象类的关键字.而且使用这个关键字定义的方法也称为抽象方法,抽象方法没有方法体,这个方法本身没有什么意义,除非被重写,而承载这个抽象方法的抽象类就必须要被继承,照这么看抽象类除了不被继承之外没有任何意义。在延伸点的说:如果声明一个抽象方法,就必须将承载这个抽象方法的类定义为抽象类,不可能在非抽象类中定义抽象方法。说的在简单点就是一个类里面有抽象方法那么这个类就必须是抽象类。
抽象类被继承后必须重写抽象类中的所有抽象方法,并且定义方法体,否则编译无法通过。
接口
接口是抽象类的延伸,可以将它看作是纯粹的抽象类,接口中的所有方法都没有方法体,所以我们上面的例子的draw()方法可以封装大到一个接口中,要使用draw()方法的类就要实现这个接口,这个就是接口存在的必要性。接口的定义语法如下:
public interface Itest{ void myaction(); //接口内的方法,省略abstract关键字 }
提示:java接口中定义方法只能被定义成public或abstract修饰符,其他的修饰符java不认识。
然后我们从新结合抽象类和接口来从新搞我们上面四边形的例子。我们先定义一个带绘制方法draw()的接口,如下:
接口定义完成后,在来定义我们Quadrangle四边形类,声明该类为抽象类,并且定义抽象方法,供其他图形类来继承该类。该抽象类定义如下:
现在定义我们的长方形类,该类继承了四边形类,重写抽象方法,并且实现接口DrawTest接口中的方法,具体如下:
,同理其他两个图形在创建的时候也要继承图形类,并且实现接口方法,我就不一一去写了,我们直接用demo实例看下结果:
和.Net一样Java也不允许多重继承,然是接口就解决这个问题,因为同一个类可以实现多个接口,但是继承多个接口是,接口之间用都好隔开,定义语法如下:
class 类名 implements 接口1,接口2,接口3,....,接口N
另外接口之间也是可以相互继承的,如果定义一个接口时使该接口继承另外一个接口,写法如下:
interface myinter1{} interface myinter2 extends myinter1{}
附: 实现一个简单的单例模式
单例模式(Singleton):这种设计模式一般用于创建一个全局的共享实例对象,该实例对象在整个应用程序中只有一个,不会出现更多的该类实例对象。实现的原理就是将类的构造方法私有化,也就是使用private修饰符来构造方法,这样外部就不能使用构造方法创建对象啦,但是本类的内部还是可以创建对象的,所以可以创建一个本类类型的成员变量来保存本类的唯一对象,然后提供属性访问器方法获取这个唯一的实例,但是每次获取都是同一个对象,而不是从新创建的。
现在用单例模式的方法创建用户类和管理员类,并且在主类演示单例模式只有一个对象。分别用两种实现单例模式的方法创建用户类和管理员类,并在主类中演示单例模式只有一个对象。先来创建一个Uers用户类,具体代码如下:
package MySinleton; public class User { private String name; private int id; private int level=1; /** *User类的唯一实例 **/ private static final User myuser = new User(); private User(){ //把构造方法私有化 } /*** * *获取唯一实例的方法 ***/ public static User getmyuser(){ return myuser; } /***==设置器和访问器==***/ public String getName() { return name; } public void setName(String name) { this.name = name; } public int getId() { return id; } public void setId(int id) { this.id = id; } public int getLevel() { return level; } public void setLevel(int level) { this.level = level; } }
然后再创建一个AdminUser管理员类,具体如下:
package MySinleton; public class AdminUser { private String name; private int id; private int level=1; /** *AdminUser类的唯一实例 **/ private static AdminUser myadminuser = new AdminUser(); /** * 获取唯一实例的方法 * **/ public synchronized static AdminUser getmyadminuser(){ if (myadminuser==null) { myadminuser = new AdminUser(); return myadminuser; } return myadminuser; } /***==设置器和访问器==***/ public String getName() { return name; } public void setName(String name) { this.name = name; } public int getId() { return id; } public void setId(int id) { this.id = id; } public int getLevel() { return level; } public void setLevel(int level) { this.level = level; } }
然后编写我们的SingletonDemo主类,并在主方法中测试单例模式。具体代码如下:
这篇有点长,东西比较多也比较杂不过都是一些基本入门的东西,好了关于Java类的继承与多态特征暂时就先学习分享这么多吧!