目录
面向对象:封装、继承、多态
什么是封装?
就是隐藏对象的属性和实现细节,仅对外提供公共访问方式。换句话说封装就是把一个对象的属性私有化,同时提供一些可以被外界访问属性的方法,如果不想被外界访问,我们大可不必提供方法给外界访问。但是如果一个类没有提供给外界访问的方法,那么这个类也没有什么意义了
封装的意义
良好的封装能够减少耦合。类内部的结构可以自由修改。可以对成员进行更精确的控制。隐藏信息,实现细节
封装代码示例
public class TestPersonDemo {
public static void main(String[] args) {
/********* begin *********/
// 声明并实例化一Person对象p
// 给p中的属性赋值
// 调用Person类中的talk()方法
Person p = new Person();
p.setName("张三");
p.setAge(18);
p.talk();
/********* end *********/
}
}
// 在这里定义Person类
class Person {
/********* begin *********/
/*
*这里对person属性进行封装
*/
private String name;
private int age;
public String getName(){
return name;
}
public void setName(String name){
this.name = name;
}
public int getAge(){
return age;
}
public void setAge(int age){
this.age = age;
}
public void talk(){
System.out.println("我是:"+name+",今年:"+age+"岁");
}
/********* end *********/
}
什么是继承?
继承是指可以让某个类型的对象获得另一个类型的对象的属性的方法
继承的好处
代码的得到了极大的重用、形成一种类的层次体系解构、为多态创造条件
继承的特性
子类内部可以访问父类非私有成员
父类的私有成员 不可以被子类继承,其他的成员都可以被子类继承
Java只支持单继承,不允许多重继承。但允许多层继承。
单继承就是一个类只能有一个父类
多重继承为一个类可以有多个父类
子类无法继承父类的构造方法
继承的示例代码
public class extendsTest {
public static void main(String args[]) {
// 实例化一个Cat对象,设置属性name和age,调用voice()和eat()方法,再打印出名字和年龄信息
/********* begin *********/
Cat c=new Cat();
c.name="大花猫";
c.age="6岁";
c.voice();
c.eat();
System.out.println(c.name+c.age);
/********* end *********/
// 实例化一个Dog对象,设置属性name和age,调用voice()和eat()方法,再打印出名字和年龄信息
/********* begin *********/
Dog d=new Dog();
d.name="大黑狗";
d.age="8岁";
d.voice();
d.eat();
System.out.println(d.name+d.age);
/********* end *********/
}
}
// 构造父类
class Animal {
/********* begin *********/
String name;
String age;
/********* end *********/
}
// Cat继承animal类
class Cat extends Animal {
// 定义Cat类的voice()和eat()方法
/********* begin *********/
public void voice(){
System.out.println(name+"喵喵叫");
}
public void eat(){
System.out.println(name+"吃鱼");
}
/********* end *********/
}
// dog继承animal类
class Dog extends Animal {
// 定义Dog类的voice()和eat()方法
/********* begin *********/
public void voice(){
System.out.println(name+"汪汪叫");
}
public void eat(){
System.out.println(name+"吃骨头");
}
/********* end *********/
}
继承条件下构造方法调用规则
如果子类的构造方法中没有通过super显示调用父类的有参构造方法,也没有通过this显示调用自身的其他构造方法,则系统会默认先调用父类的无参构造方法。在这种情况下写不写super()语句效果都是一样。
如果子类的构造方法中通过super显示调用父类的有参构造方法,那将执行父类相应构造方法,而不执行父类无参构造方法;
如果子类的构造方法中通过this显示调用自身的其他构造方法,在相应构造方法中应用以上两条规则
特别注意的是,如果存在多级继承关系,在创建一个子类对象时,以上规则会多次向更高一级父类应用,一直到执行顶级父类Object类的无参构造方法为止。
方法重写
子类从父类中继承方法,有时,子类需要修改父类中定义的方法的实现
重写的规则
重写方法的权限不能低于被重写方法的访问权限
重写方法必须与被重写方法具有相同的方法名称,参数列表和返回值类型
方法重载
方法重载是指多个方法可以享有相同的名字,但是参数的数量或类型不能完全相同
重载的规则
被重载的方法必须改变参数列表(参数个数或类型不一样)
被重载的方法可以改变返回类型
重载的方法可以改变访问修饰符
被重载的方法可以声明新的或更广的检查异常
方法能够在同一个类中或者在一个子类中被重载
无法以返回值类型作为重载函数的区分标准
重载和重写的区别
重写是父类与子类之间多态性的一种表现,重载可以理解成多态的具体表现形式
重载和重写的示例代码
public class overridingTest {
public static void main(String[] args) {
// 实例化子类对象s,调用talk()方法打印信息
/********* begin *********/
String name = "张三";
int age = 18;
String scool = "哈佛大学";
Student s = new Student(name,age,scool);
s.talk();
/********* end *********/
}
}
class Person {
/********* begin *********/
String name;
int age;
public void talk(){
}
/********* end *********/
}
class Student extends Person {
/********* begin *********/
String school;
//对方法进行重写
Student(String name,int age,String school){
this.name = name;
this.age = age;
this.school = school;
}
public void talk(){
super.talk();
System.out.println("我是:"+name+",今年:"+age+"岁,我在"+school+"上学");
}
/********* end *********/
}
什么是多态?
指一个类实例的相同方法在不同情形有不同表现形式
多态的定义格式
父类类型 变量名=new 子类类型()
多态的优点
同一段代码做不同事情
多态继承规则
通过父类引用只能访问子类对象从父类继承过来的成员但不能访问子类对象特有的成员
子类对象可以直接赋给父类引用,但父类对象在任何情况下都不可以直接赋给子类引用
只有在父类引用本身指向的就是子类对象时,才可以把父类引用强制转换为子类引用
多态的示例代码
public class TestPolymorphism {
public static void main(String[] args) {
// 以多态方式分别实例化子类对象并调用eat()方法
/********* begin *********/
Animal dog = new Dog();
dog.eat();
Animal cat = new Cat();
cat.eat();
Animal lion = new Lion();
lion.eat();
/********* end *********/
}
}
// Animal类中定义eat()方法
class Animal {
/********* begin *********/
public void eat(){
}
/********* end *********/
}
// Dog类继承Animal类 复写eat()方法
class Dog extends Animal {
/********* begin *********/
public void eat(){
System.out.println("eating bread...");
}
/********* end *********/
}
// Cat类继承Animal类 复写eat()方法
class Cat extends Animal {
/********* begin *********/
public void eat(){
System.out.println("eating rat...");
}
/********* end *********/
}
// Lion类继承Animal类 复写eat()方法
class Lion extends Animal {
/********* begin *********/
public void eat(){
System.out.println("eating meat...");
}
/********* end *********/
}
例外方法重写和重载中super的用法
super可以用来引用直接父类的实例变量。
super可以用来调用直接父类方法。
super()可以用于调用直接父类构造函数
接口定义
接口里的数据成员必须初始化,且数据成员均为常量
接口里的方法必须全部声明为abstract
,也就是说,接口不能像抽象类一样保有一般的方法,而必须全部是“抽象方法
接口的实现
接口是用于实现多继承的一种机制
接口的使用规则
接口中定义的属性值在实现类中不能被更改
一个类只能实现某个接口,不能继承某个接口
接口可以继承接口,也可以继承多个接口,接口允许多继承
若一个类只实现一个接口的部分方法,则该类必为抽象类
一个类可继承一个父类的同时实现一个或多个接口,但extends必须在implements之前
接口中的方法中不能有方法体,但抽象类可以
不可以new接口对象,但可以定义一个接口引用类型的变量并指向实现接口对象,达到多态目的
接口的作用
可实现不相关类的相同行为
提供不同对象进行协作的平台
弥补了类只能单继承的缺陷
了解一个类功能的重要途径
接口的示例代码
public class interfaceTest {
public static void main(String[] args) {
// 实例化一Student的对象s,并调用talk()方法,打印信息
/********* begin *********/
Student s = new Student();
s.talk();
/********* end *********/
}
}
// 声明一个Person接口,并在里面声明三个常量:name、age和occupation,并分别赋值,声明一抽象方法talk()
interface Person {
/********* begin *********/
String name = "张三";
int age = 18;
String occupation = "学生";
public abstract void talk();
/********* end *********/
}
// Student类继承自Person类 复写talk()方法返回姓名、年龄和职业信息
class Student implements Person {
/********* begin *********/
public void talk() {
System.out.println("学生——>姓名:"+name+",年龄:"+age+",职业:"+occupation+"!");
}
/********* end *********/
}