JavaSE 07:面向对象三大特性

面向对象三大特性

面向对象的三大特性:封装,继承,多态。

封装

1.概念

将类的某些信息隐藏在类内部,不允许外部程序直接访问,而是通过该类提供的方法来实现对隐藏信息的操作和访问。

2.代码示例

Person:

package Day4;
public class Person {
    private String name;
    private int age;
    public Person(){
        this.age=0;
        this.name=null;
    }
    public Person(String name,int age){
        this.name=name;
        this.age=age;
    }
    public void setName(String name){

        this.name=name;
    }
    public String getName(){

        return this.name;
    }
    public void setAge(int age){

        this.age=age;
    }
    public int getAge(){

        return this.age;
    }
    public String toString(){

        return "姓名:"+name+" age:"+age;
    }
}

Test:

package Day4;
public class Test {
    public static void main(String[] args) {
    Person person=new Person();
    person.setName("lyh");
    person.setAge(21);
        System.out.println(person);
    }
}

继承

1.概念

是面向对象程序设计不可缺少的设计思想,是实现代码可重用的根基,是提高代码可扩展性的主要途径。

继承是从已有的类中派生出新的类,新的类能吸收已有类的属性和行为,并能扩展新的能力。

在JAVA中使用extends关键字来表示继承关系。

JAVA不支持多继承,单继承使JAVA的继承关系很简单,一个类只能有一个直接父类。

继承之后子类可以调用父类的所有非私有属性和非私有方法。

2.super关键字

在子类构造方法中要调用父类的构造方法,需要注意:super语句只能出现在子类构造方法体的第一行。

用“super.成员变量名”来引用父类成员变量。

用“super.方法名(参数列表)”的方式访问父类的方法。

注意:super与this的区别,this通常指代当前对象,super通常指代父类。

3.继承中的构造方法

子类构造方法总是先调用父类构造方法,默认情况下,调用父类无参构造方法。

可以在子类构造方法的第一行,使用super关键字调用父类任意一个构造方法。

如果用super,必须写在方法的第一句。

如果子类的构造方法中没有显式地调用基类构造方法,则系统默认调用基类无参数的构造方法。

原因:子类创建后需要调用父类的方法,所以在创建子类对象是父类也需要同时被创建。

4.有关继承代码测试

Animal:

package Day4;

public class Animal {
   private String name;
   private  int age;
   public Animal(){
       System.out.println("Animal无参的构造方法!");
   }
   public Animal(String name,int age){
       this();
       this.name=name;
       this.age=age;
       System.out.println("Animal有参的构造方法!");
   }
   public void eat(){
       System.out.println("动物吃");
   }
   public void getInfo(){
       System.out.print("name:"+name+";"+"age:"+age);
   }
}

Dog:

package Day4;
public class Dog extends Animal{
    private String color;
    public Dog(){
        super("",0);
        System.out.println("Dog无参的构造方法!");
    }
    public Dog(String name,int age,String color){
        super(name,age);
        this.color=color;
        System.out.println("Dog有参的构造方法!");
    }

    public void getIn(){
        super.getInfo();
        System.out.println("color:"+color);
    }
}

Test:

package Day4;
public class Test {
    public static void main(String[] args) {
     Dog dog=new Dog("哈哈哈",3,"黑色");
      dog.getIn();
    }
}
5.方法的重写(方法的覆盖)(OverRide)

在子类中可以根据需要对从基类中继承来的方法进行重写。

方法重写规则:

方法名相同、参数列表相同;

返回值类型相同;

访问权限相同

即与父类方法结构完全相同

注意:构造方法不能重写

当父类的方法实现不能满足子类需求时,可以对方法进行重写( override)。

以上一个案例为主,重写eat方法:

Animal:

package Day4;

public class Animal {
   private String name;
   private  int age;
   public Animal(){
       System.out.println("Animal无参的构造方法!");
   }
   public Animal(String name,int age){
       this();
       this.name=name;
       this.age=age;
       System.out.println("Animal有参的构造方法!");
   }
   public void eat(){
       System.out.println("动物吃");
   }
   public void getInfo(){
       System.out.print("name:"+name+";"+"age:"+age);
   }
}

Dog:

package Day4;
public class Dog extends Animal{
    private String color;
    public Dog(){
        super("",0);
        System.out.println("Dog无参的构造方法!");
    }
    public Dog(String name,int age,String color){
        super(name,age);
        this.color=color;
        System.out.println("Dog有参的构造方法!");
    }
//eat方法的重写
    @Override
    public void eat() {
        super.eat();
        System.out.println("狗吃骨头!");
    }

    public void getIn(){
        super.getInfo();
        System.out.println("color:"+color);
    }
}

Test:

package Day4;
public class Test {
    public static void main(String[] args) {
     Dog dog=new Dog("哈哈哈",3,"黑色");
      dog.getIn();
      dog.eat();
    }
}
6.关联与依赖

关联是“HAS”关系,依赖是“USE”关系。

A类关联B类,指的是B类对象作为A类的属性存在,称为“has”关系。

A类依赖B类,指的是B的对象作为A类的方法参数存在,称为“use”关系。

通过以下代码测试依赖关系。

Team:

//根据依赖关系团队有多名学生,而学生也有自己相应的属性
package Day5;
import java.util.Arrays;
public class Team {
   private String subject;
   private Student[] student;
   public Team(Student[] student) {

       this.student = student;
   }

   public String getSubject() {

       return subject;
   }

   public void setSubject(String subject) {

       this.subject = subject;
   }

   public Student[] getStudent() {
       return student;
   }

   public void setStudent(Student[] student) {
       this.student = student;
   }

   @Override
   public String toString() {
       return "Team{" +
               "subject='" + subject + '\''+

               ","+" student=" + Arrays.toString(student) +
               '}';
   }
}

Student:

package Day5;

public class Student {
  private  String  id;
  private String name;
  private int age;
    public Student(){
    this.id=null;
    this.name=null;
    }
    public Student(String id,String name,int age){
    this.name=name;
    this.id=id;
    this.age=age;
    }
    public String getId() {

        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    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;
    }

    @Override
    public String toString() {
        return "Student{" +
                "id='" + id + '\'' +
                ", name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

该团队有5名学生,并输出学生基本信息。

Test:

package Day5;

import java.lang.reflect.Array;
import java.util.Arrays;

public class Test {
    public static void main(String[] args) {
        Student student[]=new Student[5];
        student[0]=new Student("1822","cjr",21);
        student[1]=new Student("1823","cyx",21);
        student[2]=new Student("1825","lyh",23);
        student[3]=new Student("1820","ccc",22);
        student[4]=new Student("1827","jij",25);
        Team team=new Team(student);
        team.setSubject("智能算法");
        System.out.println(team);
        System.out.println(Arrays.toString(student));
        System.out.println(Arrays.toString(team.getStudent()));
    }
}

多态

1.概念

同一种事物,在不同时刻表现不同的状态

多态存在的三个必要条件

要有继承(包括接口的实现)(前提条件)

要有重写(前提条件)

父类引用指向子类对象

Animal:

package Day5;
public class Animal {
   private String name;
   private int age;
   public void eat(){
       System.out.println("Animal吃");
   }
  public static  void say(){
      System.out.println("Animal叫");
  }
    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;
    }
}

Dog:

package Day5;

public class Dog extends Animal{
    private String type;
    public void eat(){
        System.out.println("Dog吃骨头");
    }
    public static void say(){
        System.out.println("Dog旺旺");
    }
   public void sleep(){
       System.out.println("Dog睡觉");
   }
}

Cat:

package Day5;

public class Cat extends Animal{
    private String type;
    public void eat(){
        System.out.println("cat吃饭");
    }
    public static void say(){
        System.out.println("Cat喵喵");
    }
    public void study(){
        System.out.println("Cat学习");
    }
}

Test:

package Day5;

import java.lang.reflect.Array;
import java.util.Arrays;

public class Test {
    //多态的体现
    public void run(Animal animal){
        animal.eat();
    }
    public static void main(String[] args) {
        Test test=new Test();
     Animal  dog=new Dog();
     dog.eat();//编译看左边,运行看右边。eat方法被重写
     dog.say();//静态方法编译运行看左边,因为静态变量静态方法都存储在方法区。
     Dog dog0=(Dog)dog;//建议在使用向下转型的时候考虑使用instanceof判断是否为该类型,避免异常。
     dog0.sleep();
     dog0.eat();
     Animal cat=new Cat();
     cat.eat();
     Cat cat0=(Cat)cat;
     cat0.eat();
     cat0.study();
     test.run(cat);
     test.run(dog);
    }
}

注意:对于静态方法没有必要去重写,静态方法,成员变量都是编译运行看左边。

静态加载优先于main方法。

2.final关键字

final 用于声明属性,方法和类

属性:定义就必须直接赋值或者在构造方法中进行赋值,并且后期都不能修改。

方法:子类里不可被覆盖(重写)。

类:不能被定义为抽象类或是接口,不可被继承。

在声明时同时赋值,往往与static一起使用

声明时不赋值,必须在构造方法中逐一赋值

总的原则:保证创建每一个对象的时候,final属性的值是确定的。

在方法参数前面加final关键字,为了防止数据在方法体中被修改。

package Day5;
public class keyword_final {
    final static int  acc=10;//必须赋值
    static int num0;
       final  int num;//可以在构造方法中赋值
       public keyword_final(int num){
           this.num=num;
       }
       public void test(){
           final int num;

       }
    public static void main(String[] args) {
        keyword_final key0=new keyword_final(10);
        keyword_final key1=new keyword_final(11);
    }
}
package Day5;
public class keyword_final {
    final static int a=0;//final定义的变量如果是成员变量必须初始化。
    public static void main(String[] args) {
    final int b=10;
        System.out.println(a);
        //此调用涉及静态方法只能调用静态静态标量或者静态方法。所以a必须是静态变量类似于递归算法。
    }
}
3.抽象类

用abstract修饰的类就是抽象类。如果某个类中包含有抽象方法,那么该类就必须定义成抽象类。

抽象方法是一种特殊的方法:它只有声明,而没有具体的实现。

抽象方法必须用abstract关键字进行修饰。

抽象类可以有成员属性和非抽象的成员方法。

抽象类不能被实例化,但可以有构造函数,因为抽象类中含有无具体实现的方法,所以不能用抽象类创建对象。

抽象类只能用作基类,表示的是一种继承关系。继承抽象类的非抽象类必须实现其中的所有抽象方法,而已实现方法的参数、返回值要和抽象类中的方法一样。否则,该类也必须声明为抽象类。

构造方法和静态方法不可以修饰为abstract。

Shape:

package Day5;

public abstract class Shape {
    int name;
    public abstract double getArea();//定义抽象方法 求面积 无方法体只声明不实现 抽象类不能被实例化只能通过子类实现。
    public abstract  double getPerimeter();//求周长
}

Circle:

package Day5;
public class Circle extends Shape {
    private double r;
    public double getR() {
        return r;
    }
    public void setR(double r) {
        this.r = r;
    }
    @Override
    public double getArea() {
        return Math.PI*r*r;
    }
    @Override
    public double getPerimeter() {
        return 2*Math.PI*r;
    }
}

Rectangle:

package Day5;

public class Rectangle extends Shape{
    private double length;
    private double width;
    public double getWidth() {
        return width;
    }
    public void setWidth(double width) {
        this.width = width;
    }
    public double getLength() {
        return length;
    }
    public void setLength(double length) {
        this.length = length;
    }
    @Override
    public double getPerimeter() {
       return (length+width)*2;
    }
    @Override
    public double getArea() {
       return length*width;
    }
}

Test:

package Day5;
import java.util.*;
public class Test {
    public void run(Shape shape) {
        System.out.println("面积:"+shape.getArea());
        System.out.println("周长"+shape.getPerimeter());
    }
    public static void main(String[] args) {
        Scanner sc=new Scanner(System.in);
        Test test=new Test();
        System.out.println("请输入圆的半径:");
        double r=sc.nextDouble();
        Shape circle=new Circle();
        Circle c=(Circle)circle;
        c.setR(r);
        System.out.println("半径为:"+r+"的圆:");
        test.run(circle);
        System.out.println("请输入长方形的长:");
        double length=sc.nextDouble();
        System.out.println("请输入长方形的宽:");
        double width=sc.nextDouble();
        Shape rectangle=new Rectangle();
        System.out.println("长度为"+length+"宽度为"+width+"的长方形:");
        Rectangle re=(Rectangle) rectangle;
        re.setLength(length);
        re.setWidth(width);
        test.run(rectangle);
    }
    }

instanceof在此案例中的测试出现警告

因为此案例中结果返回值一直是true。

只是修改了上一个案例的Test类方法。

package Day5;
import java.util.*;
public class Test {
    public void run(Shape shape) {
        System.out.println("面积:"+shape.getArea());
        System.out.println("周长"+shape.getPerimeter());
    }
    public static void main(String[] args) {
        Scanner sc=new Scanner(System.in);
        Test test=new Test();
        System.out.println("请输入圆的半径:");
        double r=sc.nextDouble();
        Shape circle=new Circle();
        if(circle instanceof Circle) {
            Circle c = (Circle) circle;
            c.setR(r);
            System.out.println("半径为:" + r + "的圆:");
            test.run(circle);
        }
        System.out.println("请输入长方形的长:");
        double length=sc.nextDouble();
        System.out.println("请输入长方形的宽:");
        double width=sc.nextDouble();
        Shape rectangle=new Rectangle();
        System.out.println("长度为"+length+"宽度为"+width+"的长方形:");
        if(rectangle instanceof Rectangle) {
            Rectangle re = (Rectangle) rectangle;
            re.setLength(length);
            re.setWidth(width);
            test.run(rectangle);
        }
    }
    }
4.接口

接口是隐式抽象的,当声明一个接口的时候,不必使用abstract关键字。

接口中每一个方法也是隐式抽象的,默认为public abstract 。

接口中声明的属性默认为 public static final 的。

接口不是被类继承了,而是要被类实现。

接口不能实例化对象(无构造方法),但可以声明对象的引用。(多态性)

多个类可以实现同一个接口。

一个类可以实现多个接口,但只能继承一个类。

与继承关系类似,接口与实现类之间存在多态性。

一个接口能继承其它多个接口。

当类实现接口的时候,类要实现接口中所有的方法。否则,类必须声明为抽象的类。

5.抽象类与接口的区别

语法上的区别

1。抽象类里可以有构造方法,而接口内不能有构造方法。

2。抽象类中可以有普通成员变量,而接口中不能有普通成员变量。

3。抽象类中可以包含非抽象的普通方法,而接口中所有的方法必须是抽象的。

4。抽象类中的抽象方法的访问类型可以是public ,protected和默认类型,但接口中的抽象方法只能是public类型的,并且默认即为public abstract类型。

5。抽象类中可以包含静态方法,接口内不能包含静态方法。

6。抽象类和接口中都可以包含静态成员变量,抽象类中的静态成员变量的访问类型可以任意,但接口中定义 静态常量。

相同点

1。抽象类和接口都不能用来创建对象。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值