面向对象:继承,封装,多态
封装:
封装是什么
封装:
将一个事物的属性,私有化(对外进行隐藏),外界不能直接访问(保证了数据安全性),需要提供对外的
公共访问来访问成员变量!
private:
私有的,外界无法访问的,只能在本类中访问
private关键字的特点:
被private修饰的成员变量/成员方法,都只能在本类中访问;
外界类不能直接访问,但是可以通过公共方法间接访问
class Student{//定义一个学生类
//成员变量:name,age 私有化
private String name ;
private int age ;
//给学生姓名赋值get(xxx)/set(xxx)
public void setName(String n){ //"高圆圆"
name = n ;
}
//给年龄赋值
public void setAge(int a){ // 30
age = a ;
}
//获取姓名
public String getName(){
return name ;
}
//获取年龄
public int getAge(){
return age ;
}
//成员方法:学习
public void study(){
System.out.println("学习Java") ;
}
}
//测试类
class StudentTest{
public static void main(String[] args){
//创建一个学生类对象
Student s = new Student() ;
System.out.println(s.getName()+"---"+s.getAge()) ;
//公共访问:setXXX()赋值
s.setName("张三") ;
s.setAge(15) ;
//公共访问方法:setXXX()获取值
System.out.println(s.getName()+"---"+s.getAge()) ;
}
}
继承:
什么是继承:
继承是将多个类的共性内容抽取在一个独立的类中,然后独立的类和这些类产生一种"继承"关系
继承的好处:
1)提高了代码的复用性
2)提高了的代码的维护性
3)让类与类之间产生关系 是 "多态的前提条件"
继承的格式:
class 父类名{}
class 子类名 extends 父类名{}
class Person{//父类
private String name ;//定义成员变量
prvate int age ;
public Person(){}
//有参构造方法
//setXXX()/getXXX()
}
class Student extends Person{}//直接调用父类中的成员变量
class Teacher extends Person{}//直接调用父类中的成员变量
继承特点:
注意事项:
子类继承父类,只能继承父类非私有的成员,私有的成员,外界不能访问的,只能间接通过公共方法访问!
子类中的功能:一般都是一些子类的特有功能
1)在Java中,类与类之间的继承关系,只支持单继承,不支持多继承!但是可以多层继承!
继承中,一个类的组成
1)成员变量
2)构造方法
3)成员方法
//定义两个父类
class GrandFather{
public void function(){
System.out.println("我是爷爷...") ;
}
}
class Father extends GrandFather{
public void method(){
System.out.println("我是爸爸...") ;
}
}
//子类
//class Son extends Father,Monther{} 多继承:Java语言中:类与类之间不支持
//正常的写法:单继承
class Son extends Father{
public void show(){
System.out.println("我是孙子...") ;
}
}
//测试类
class ExtendsDemo{
public static void main(String[] args){
//创建子类对象
Son son = new Son() ;
son.show() ;
son.method() ;
son.function() ;
}
}
继承的使用场景:
继承的中的另一个注意事项
不要为了使用部分功能,而使用继承!
如果A类是B类的一种,或者B类是A类的一种,这个时候使用继承!
继承的体现出的是一种"is a"的关系:xxx 是xxx的一种.
举例:"苹果,香蕉,橘子是水果的一种"
class Person{ //"父类"
private String name ;
private int age ;
public Person(){}
//构造方法赋值
public Person(String name,int age){
this.name = name ;
this.age = age ;
}
public void setName(String name){
this.name = name ;
}
public void setAge(int age){
this.age = age ;
}
public String getName(){
return name ;
}
public int getAge(){
return age ;
}
public void eat(){
System.out.println("饿了就需要eat") ;
}
public void sleep(){
System.out.println("累了就需要sleep") ;
}
}
//学生类和工人类 (子类)
class Student extends Person{}
class Worker extends Person{}
//测试类
class ExtendsDemo{
public static void main(String[] args){
//使用继承了
//方式:通过无参+setXXX()
Student s = new Student() ;
s.setName("学生") ;
s.setAge(8) ;
System.out.println(s.getName()+"---"+s.getAge()) ;
s.eat() ;
s.sleep() ;
Worker w = new Worker() ;
w.setName("工人") ;
w.setAge(30) ;
System.out.println(w.getName()+"---"+w.getAge()) ;
w.eat() ;
w.sleep() ;
}
}
继承中成员变量访问问题
在继承中,成员变量访问问题!
1)子类继承父类,如果子类的成员变量名称和父类的成员变量名称不一致的情况:
比较简单,分别访问即可
2)子类继承父类,如果子类的成员变量名称和父类的成员变量名称一致的情况:
a)现在本类的局部位置找,有没有这个变量,如果有就直接使用
b)如果本类的局部位置没有,在本类的成员位置中找,如果有,就使用
c)如果本类的成员位置没有,在它的父类的成员位置找,如果有,就使用
d)父类的成员位置都没有这个变量,压根不存在,就报错!
遵循一个原则:"就近原则"
多态:
多态是啥,及遵循的条件
多态:一个事物在不同时刻体现的不同形态(内存中的变化)
要使用多态,要遵循它的前提条件:
1)必须存在继承关系 (没有继承关系,没有多态!)
2)必须有方法重写 (子类继承父类,需要将父类的功能覆盖掉)
使用子类的功能;
3)必须存在父类引用指向子类对象("向上转型")
class Fu{}
class Zi extends Fu{}
之前:Zi zi = new Zi() ;
现在:多态: Fu f = new Zi() ;
//父类
class Fu{
public Fu(){
System.out.println("父类的无参构造方法");
}
int num = 20 ;
public void show(){
System.out.println("show Fu");
}
//静态方法
public static void function(){
System.out.println("function Fu");
}
}
//子类
class Zi extends Fu{
public Zi(){
//super();
System.out.println("子类的无参构造方法");
}
int num = 30 ;
//重写
public void show(){
System.out.println("show Zi");
}
//静态方法
public static void function(){
System.out.println("function Zi");
}
}
//测试类
public class DuoTaiDemo {
public static void main(String[] args) {
//父类引用指向子类对象
Fu f = new Zi() ; //向上转型
System.out.println(f.num);
f.show() ;
f.function();
多态的好处
多态的好处是什么?
1)可以提高代码的复用性 (是由继承保证的)
2)可以提高代码的扩展性(多态完成:父类引用指向子类对象:Fu f = new Zi()) ;
多态的弊端:
多态的弊端:
不能访问子类的特有功能!
向上转型:父类引用指向子类对象
如果能够使用子类型,就可以访问它的功能!
解决方案:
1)子类 引用 指向自己本身:子类对象
虽然可以访问,但是多态中,不推荐,因为重新new 对象,消耗堆内存空间
2) 将父类引用强制转换为子类引用 :向下转型 ,前提:必须存在向上转型
Fu f = new Zi() ;//向上转型
Zi z = (Zi)f ; //向下转型
推荐2) :不会重新在堆内存中开辟空间,结束内存空间!
//父类
class Father{
public void show(){
System.out.println("show Father...");
}
}
//子类
class Son extends Father{
public void show(){
System.out.println("show Zi...");
}
//子类的特有功能
public void playGame(){
System.out.println("可以玩游戏...");
}
}
//测试类
public class DuoTaiDemo3 {
public static void main(String[] args) {
//多态的创建对象
Father father = new Son() ; //向上转型:父类引用指向子类对象
father.show() ;
// father.playGame() ;
Son s = new Son() ;
s.playGame();
Son s2 = (Son) father; //向下转型
s2.playGame();
}
}
多态的向下转型
2) 将父类引用强制转换为子类引用 :向下转型 ,前提:必须存在向上转型
Fu f = new Zi() ;//向上转型
Cat2 c = (Cat2)a ; //向下转型
Cat2 c = (Cat2)a ; :不会重新在堆内存中开辟空间,结束内存空间!
多态的向下转型,如果使用不当,会出现异常!
ClassCastException:类转换异常: 堆内存中的变化 和接收的类型不匹配!
//父类
class Animal2{
}
//子类
class Cat2 extends Animal2{
}
class Dog2 extends Animal2{}
//测试类
public class DuoTaiDemo4 {
public static void main(String[] args) {
//多态创建对象
Animal2 a = new Cat2() ; //堆内存中猫的实例 (猫是动物)
Cat2 c = (Cat2)a ; //将猫还原了 (猫是猫) 向下转型
a = new Dog2() ;//堆内存中是狗的实例(狗是动物)
Dog2 d = (Dog2)a; //还原成狗了
// Cat2 c2 = (Cat2)a; //ClassCastException:类转换异常:属于运行时期异常!
}
}