目录
面向对象语言的三大特征:
封装:
含义:
1、包装,例如我们将一些常用的功能进行抽取,定义成一个方法
2、面向对象特征中的封装:隐藏,对类中的成员对外是否可见进行控制
使用权限修饰符控制成员对外可见性
封装案例1:将类中属性私有化
代码
package com.ffyc.javaopp.day3.fz;
public class Person {
/*
将成员变量设置为私有权限,在其他类中就不能直接访问
*/
private String name;
private int age;
public Person(){
}
//提供公共权限构造方法,外部可以通过构造方法对私有成员进行赋值
//但是需要使用成员变量的值时,就不能获取到
public Person(String name,int age) {
if(name.length() > 2 && name.length() < 5){
this.name = name;
}
if(age >= 0 && age < 150){
this.age = age;
}
}
//给私有属性对外提供的公共权限的方法进行赋值和值的获取
public void setName(String name){
if(name.length() > 2 && name.length() < 5){
this.name = name;
}
}
public String getName(){
return this.name;
}
public void setAge(int age){
if(age >= 0 && age < 150){
this.age = age;
}
}
public int getAge(){
return this.age;
}
}
package com.ffyc.javaopp.day3.fz;
public class Test {
public static void main(String[] args) {
//Person person = new Person("aaaaaaaaaa",2222222);
//在外部没有办法赋值时进行控制
//person.name = "aaaaaaaaaaaaa";
//person.age = 22222222;
Person p = new Person();
p.setName("chh");
p.setAge(20);
System.out.println(p.getName());
System.out.println(p.getAge());
}
}
package com.ffyc.javaopp.day3.fz;
public class Car {
private String name;
private String color;
private int age;
//给私有属性对外提供操作的公共方法
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
代码展示
封装案例2:将某些方法私有化
java设计模式(模板,固定套路 )
解决一类问题的固定方式
单例模式:单个实例,在系统中,想让某个类只能创建一个对象
代码
package com.ffyc.javaopp.day3.fz;
public class MyWindow {
static int num = 0;
static MyWindow myWindow = null;
//将构造方法私有化,这样在其他类中,就无法使用构造方法,就不能创建对象
private MyWindow(){
}
//对外提供的获取位移对象的公共方法
public static MyWindow getMyWindow(){
if(myWindow==null){
myWindow = new MyWindow();
}
return myWindow;
}
}
package com.ffyc.javaopp.day3.fz;
public class TestMyWindow {
public static void main(String[] args) {
/*new MyWindow();
new MyWindow();
new MyWindow();
new MyWindow();*/
System.out.println(MyWindow.getMyWindow());
System.out.println(MyWindow.getMyWindow());
System.out.println(MyWindow.getMyWindow());
System.out.println(MyWindow.getMyWindow());
}
}
运行展示
继承
概念:
子继承父 儿子就可以拥有父亲的功能
面向对象语言也引入了继承的思想
猫和狗 都用有名字,年龄,吃东西的属性和行为
可以将这些共性的属性和行为进行抽取,这样就不需要在每个类中定义同样的属性和行为,只需要类与类之间建立继承关系
举例:
猫和狗 都是动物,他们都有名字,年龄,吃东西
抽取一个动物类
名字,年龄,吃东西
猫类 继承 动物类
猫抓老鼠
狗类 继承 动物类
看家
java中如果一个类没有使用extends关键字显示的继承其他类
那么这个类默认继承自Object类
Object类是java类体系中最顶级的一个类
所有类都直接或间接的继承Object类
package com.ffyc.javaopp.day3.jc.demo1;
public class Animal {
private String name;
private int age;
public void eat(){
System.out.println("动物吃东西");
}
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;
}
}
package com.ffyc.javaopp.day3.jc.demo1;
/*
猫类 继承 动物类
extends
猫类 子类/派生类
动物类 父类/基类
*/
public class Cat extends Animal{
public void lookHome(){
System.out.println("猫可以抓老鼠");
}
}
子类继承父类后,拥有父类所有的实例变量和方法
但是不能直接访问私有成员
java中一个类不能继承多个类
只能直接继承一个类,但是可以多层继承
package com.ffyc.javaopp.day3.jc.demo1;
/*
狗类 继承 动物类
extends
狗类 子类/派生类
动物类 父类/基类
*/
public class Dog extends Animal{
public void lookHome(){
System.out.println("狗可以看家");
}
}
package com.ffyc.javaopp.day3.jc.demo1;
public class Test {
public static void main(String[] args) {
Dog dog = new Dog();
dog.setName("黑子");
dog.setAge(5);
dog.eat();
System.out.println(dog.getName()+":"+dog.getAge());
Cat cat = new Cat();
cat.setName("厌世脸");
cat.setAge(10);
cat.eat();
System.out.println(cat.getName()+":"+cat.getAge());
Seconddog seconddog = new Seconddog();
seconddog.setName("豆豆");
seconddog.setAge(7);
seconddog.eat();
seconddog.lookHome();
seconddog.friend();
seconddog.hashCode();
System.out.println(seconddog.getName()+":"+seconddog.getAge());
}
}
好处:
减少代码冗余,提高代码复用性
提高程序功能的扩展性(分别在猫和狗类中维护他们各自特有的属性和行为)
什么时候使用继承?
猫是动物
狗是动物 满足什么是什么 is-a
方法重写:
package com.ffyc.javaopp.day3.jc.demo2;
public class Animal {
private String name;
private int age;
public void eat(){
System.out.println("动物吃东西");
}
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;
}
}
方法的重写
有时候,父类方法中的实现(父类方法中为完成功能所写的代码),不能满足子类中的需要 (与子类中的实现不同)
就可以将父类中的方法在子类中进行重写(在子类中对父类中的方法进行重新定义)
这样子类中的重写的方法,就会覆盖掉父类中方法
重写方法时的语法规则:
方法名相同,参数相同
方法返回值类型相同
子类重写的方法权限必须等于或大于父类方法的权限
子类重写的方法结构应与父类方法结构一致
package com.ffyc.javaopp.day3.jc.demo2;
/*
*/
public class Dog extends Animal{
/*
@Override注解标记(标签),对方法进行标识,表示此方法是从父类中重写来的
在编译期间,会进行语法检测
*/
@Override
public void eat() {
System.out.println("狗吃骨头");
}
/*public void eat(){
System.out.println("狗吃骨头");
}*/
public void lookHome(){
System.out.println("狗可以看家");
}
}
package com.ffyc.javaopp.day3.jc.demo2;
public class Test {
public static void main(String[] args) {
Dog dog = new Dog();
dog.eat();
}
}
super关键字
在子类中使用super关键字,访问父类中定义的那部分成员
super.成员变量
super.成员方法(常用)当子类中重写了父类方法时,为了区分调用的是父类中还是子类中重写的方法,使用super调用父类中的
super()表示调用父类中构造方法
package com.ffyc.javaopp.day3.jc.demo3;
public class Animal {
private String name;
private int age;
public void eat(){
System.out.println("动物吃东西");
}
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;
}
}
package com.ffyc.javaopp.day3.jc.demo3;
/*
*/
public class Dog extends Animal {
@Override
public void eat() {
super.eat();//调用父类中的eat()
System.out.println("狗吃骨头");//扩展自己类吃东西的功能
}
public void lookHome(){
//this.eat();调用的是当前对象的eat()
super.eat();//在子类中调用父类中定义的那部分成员
System.out.println("狗可以看家");
}
}
package com.ffyc.javaopp.day3.jc.demo3;
public class Test {
public static void main(String[] args) {
Dog dog = new Dog();
dog.lookHome();
}
}
继承中的构造方法的调用:
总是在子类的构造方法中,使用super()调用父类中的构造方法
为了确保对父类成员进行初始化
package com.ffyc.javaopp.day3.jc.demo4;
public class Animal {
private String name;
private int age;
public Animal(){
super();
System.out.println("animal无参构造方法");
}
public Animal(String name, int age) {
this.name = name;
this.age = age;
}
public void eat(){
System.out.println("动物吃东西");
}
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;
}
}
默认在子类中的构造方法中,会默认调用父类中的构造方法
每当创建子类对象时,会调用子类构造方法,在子类构造方法中调用父类构造方法
而且在子类构造方法的第一行就会调用父类构造方法,先确保父类中的成员被初始化
子类构造方法中默认会调用父类无参构造方法、
如果需要显示的使用super调用,必须放在构造方法的第一行
还可以调用父类中指定的构造方法
package com.ffyc.javaopp.day3.jc.demo4;
/*
*/
public class Dog extends Animal {
public Dog(){
//super();
System.out.println("dog无参构造方法");
}
public Dog(String name, int age) {
super(name, age);
}
@Override
public void eat() {
System.out.println("狗吃骨头");//扩展自己类吃东西的功能
}
public void lookHome(){
System.out.println("狗可以看家");
}
}
package com.ffyc.javaopp.day3.jc.demo4;
public class Test {
public static void main(String[] args) {
Dog dog = new Dog();
new Dog("旺财",5);
}
}
多态
多态 向上转型 好处
package com.ffyc.javaopp.day3.dt;
public abstract class Aniaml {
private String name;
private int age;
public abstract void eat();
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;
}
}
package com.ffyc.javaopp.day3.dt;
public class Dog extends Aniaml{
@Override
public void eat() {
System.out.println("狗吃骨头");
}
}
package com.ffyc.javaopp.day3.dt;
public class Cat extends Aniaml{
@Override
public void eat() {
System.out.println("猫吃鱼");
}
}
人喂动物
使用父类Aniaml,可以接收任意的子类(猫,狗)
只需要定义一个方法,处理不同的子类
提高程序的扩展性(只需要添加其他的类,大象,企鹅)
人喂狗, 由于参数类型是Dog,只能接收Dog类型,为每一种动物定义一个方法
不便于程序的扩展,每添加一种类型,就需要修改代码
package com.ffyc.javaopp.day3.dt;
public class Person {
/*
人喂动物
使用父类Aniaml,可以接收任意的子类(猫,狗)
只需要定义一个方法,处理不同的子类
提高程序的扩展性(只需要添加其他的类,大象,企鹅)
*/
public void feedAnimai(Aniaml aniaml){
aniaml.eat();
}
/* *//*
人喂狗, 由于参数类型是Dog,只能接收Dog类型,为每一种动物定义一个方法
不便于程序的扩展,每添加一种类型,就需要修改代码
*//*
public void feedDog(Dog dog){
dog.eat();
}
*//*
人喂猫
*//*
public void feedCat(Cat cat){
cat.eat();
}*/
}
多态--多种状态
同一个父类可以表示不同的子类对象,状态就不同了
父类的引用指向子类对象,两个类之间必须是继承关系
把子类类型转为父类类型,同一个父类在不同时候,表示不同状态(子类)
package com.ffyc.javaopp.day3.dt;
public class Test {
public static void main(String[] args) {
/*
new哪一个类的对象,就用哪个类的类型表示,一个个都是孤立的,独立的
Dog dog = new Dog();
Cat cat = new Cat();
Person person = new Person();
person.feedDog(dog);
person.feedCat(cat);*/
Aniaml dog = new Dog();
Aniaml cat = new Cat();
Person person = new Person();
person.feedAnimai(dog);
person.feedAnimai(cat);
}
}
注意事项
多态环境下对成员方法的调用
package com.ffyc.javaopp.day3.dt;
public abstract class Aniaml {
private String name;
private int age;
public abstract void eat();
public void sleep(){
System.out.println("动物睡觉");
}
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;
}
}
package com.ffyc.javaopp.day3.dt;
public class Dog extends Aniaml{
@Override
public void eat() {
System.out.println("狗吃骨头");
}
@Override
public void sleep() {
System.out.println("狗睁着眼睛睡觉");
}
public void lookHome(){
}
}
package com.ffyc.javaopp.day3.dt;
public class Cat extends Aniaml{
@Override
public void eat() {
System.out.println("猫吃鱼");
}
public void catchMouse(){
}
}
多态注意事项:
注意成员调用时分为编译期间和运行期间
编译期间:写代码时,由于类型上升为父类类型,所以只能调用到父类中定义成员
运行期间:运行代码时,实际调用的是子类中重写的方法
对非静态成员方法:
编译看左边,运行看右边
package com.ffyc.javaopp.day3.dt;
public class Test1 {
public static void main(String[] args) {
Aniaml dog = new Dog();
Aniaml cat = new Cat();
dog.eat();
cat.eat();
dog.sleep();//对于子类如果没有重写父类中的方法,那么调用的是子类对象中父类的方法
cat.sleep();
}
}
多态环境下对 静态成员方法 和 成员变量 的调用
package com.ffyc.javaopp.day3.dt;
public abstract class Aniaml {
private String name;
private int age;
int num = 10;
public abstract void eat();
public void sleep(){
System.out.println("动物睡觉");
}
public static void show(){
System.out.println("animal中的show()");
}
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;
}
}
package com.ffyc.javaopp.day3.dt;
public class Dog extends Aniaml{
int num = 20;
@Override
public void eat() {
System.out.println("狗吃骨头");
}
@Override
public void sleep() {
System.out.println("狗睁着眼睛睡觉");
}
public static void show(){
System.out.println("dog中的show()");
}
public void lookHome(){
}
}
package com.ffyc.javaopp.day3.dt;
public class Cat extends Aniaml{
@Override
public void eat() {
System.out.println("猫吃鱼");
}
public void catchMouse(){
}
}
对于静态成员方法h和成员变量:
都是编译看左边,运行也是看左边
package com.ffyc.javaopp.day3.dt;
public class Test1 {
public static void main(String[] args) {
Aniaml dog = new Dog();
Aniaml cat = new Cat();
dog.eat();
cat.eat();
dog.sleep();//对于子类如果没有重写父类中的方法,那么调用的是子类对象中父类的方法
cat.sleep();
dog.show();
System.out.println(dog.num);
}
}
向下转型
package com.ffyc.javaopp.day3.dt;
public abstract class Aniaml extends Object{
private String name;
private int age;
int num = 10;
public abstract void eat();
public void sleep(){
System.out.println("动物睡觉");
}
public static void show(){
System.out.println("animal中的show()");
}
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;
}
}
package com.ffyc.javaopp.day3.dt;
public class Dog extends Aniaml{
int num = 20;
@Override
public void eat() {
System.out.println("狗吃骨头");
}
@Override
public void sleep() {
System.out.println("狗睁着眼睛睡觉");
}
public static void show(){
System.out.println("dog中的show()");
}
public void lookHome(){
System.out.println("狗看家");
}
}
package com.ffyc.javaopp.day3.dt;
public class Cat extends Aniaml{
@Override
public void eat() {
System.out.println("猫吃鱼");
}
public void catchMouse(){
}
}
package com.ffyc.javaopp.day3.dt;
public class Person {
/*
人喂动物
使用父类Aniaml,可以接收任意的子类(猫,狗)
只需要定义一个方法,处理不同的子类
提高程序的扩展性(只需要添加其他的类,大象,企鹅)
*/
public void feedAnimai(Aniaml aniaml){
aniaml.eat();
//判断animal变量,实际运行时表示的是否是Dog类型
if(aniaml instanceof Dog){
Dog dog = (Dog)aniaml;
dog.lookHome();
}
}
/* *//*
人喂狗, 由于参数类型是Dog,只能接收Dog类型,为每一种动物定义一个方法
不便于程序的扩展,每添加一种类型,就需要修改代码
*//*
public void feedDog(Dog dog){
dog.eat();
}
*//*
人喂猫
*//*
public void feedCat(Cat cat){
cat.eat();
}*/
}
为了实现多态性,我们将子类类型向上转为父类类型
但是一旦类型上升为父类类型,那么就调用不到子类中特有的方法
这个就是多态在某种情况下的缺点
解决办法:
就行向下转型,把父类类型转为子类类型
package com.ffyc.javaopp.day3.dt;
public class Test2 {
public static void main(String[] args) {
Aniaml dog = new Dog();
Aniaml cat = new Cat();
dog.eat();
cat.eat();
//Dog dog1 = (Dog)dog;
//dog1.lookHome();
Person person = new Person();
person.feedAnimai(dog);
person.feedAnimai(cat);
}
}