Java面向对象特点
面向对象的三大特点:封装,继承,多态;
1.封装:
1.简介:
把抽象出的属性,方法封装在一起,数据被保护在内部,程序的其它部分只有通过被授权的操作(方法)才能对数据进行操作;
2.封装好处:
a:隐藏实现细节,b:对数据进行验证保证安全合理;
3.封装实现步骤:
1.将成员(属性,方法)私有化:private,外部就不能直接修改属性;
2.提供一个(公共的)public set方法:用于对成员(属性,方法)进行判断和赋值;
arduino
eg: public void set xxx(类型,方法名) { //修改对象属性,与构造器不同(初始化对象!!!)
1.加入数据验证的业务逻辑;
2.属性=参数名;eg:this.name=name;
}
3.提供一个(公共)public get方法,用于获取属性的值:
kotlin
public 数据返回类型 get xxx(){ //间接访问私有属性!
return xx;
}
4.快速入门:
java
//1.快速入门:设置不能随便访问年龄,工资等信息,并设置合理验证;
import java.util.Scanner;
public class encap01 {
public static void main(String[]name){
Scanner myScanner=new Scanner(System.in);
Person person=new Person();
//p.age=18;因为私有化所以不可以对其进行操作;
//3.调用set方法
person.setName("kunkun");
person.setAge(18);
person.setTime(2.5);
System.out.println(person.info());
}
}
class Person{
//1.将属性私有化;
String name;
private int age;
private double time;
//2.分别提供public set和get方法
public void setName(String name){//2a:提供public set方法:判断赋值
//因为要判断赋值,所以要把name传进去
this.name=name;
}
public String getName(){ //提供public get方法:返回
return name;
}
public void setAge(int age){//b:
if(age>=1&&age<=120) {
this.age = age;
}else{
System.out.println("你输入的年龄不对,年龄需要在1-120之间,返回默认值是:18");
this.age=18;
}
}
public int getAge(){
return age;
}
public void setTime(double time){//c
if(time>=1&&time<=100) {
this.time = time;
}else{
System.out.println("输入time有误,请输入正确的time");
}
}
public double getTime(){
return time;
}
public String info(){//方法:输出信息
return "信息是:name="+name+"age="+age+"time="+time;
}
}
5.练习:
java
练习:定义两个类,Account和AccountTest类
要求:1.Account类具有属性:姓名(长度2-4位),余额(>20),密码(必须是6位),如果不满足则给出提示信息,并给默认值;
2.通过setxxx方法给Acount的属性赋值
3.在AccountTest类中测试
public class encap01 {
public static void main(String[]ages){
Account a=new Account();
a.setName("坤坤");
a.setBalance(25.0); //调用方法;赋值检查
a.setMima("123456");
a.info();//调用方法输出
}
}
class Account{
//1.private 全部封装;
private String name;
private double balance;
private String mima;
//2.public get与set检查和赋值
public void setName(String name){//2a:!!
if(name.length()>=2&&name.length()<=4) {
this.name = name;
}else{
System.out.println("你输入的name不正确");
}
}
public String getName(){
return name;
}
public void setBalance(double balance){//2b
if(balance>20) {
this.balance = balance;
}else{
System.out.println("你输入的balance不正确");
}
}
public double getBalance(){
return balance;
}
public void setMima(String mima){//2c
if(mima.length()==6) {
this.mima = mima;
}else{
System.out.println("你输入的密码不正确");
}
}
public String getMima(){
return mima;
}
//3.输出方法:
public void info(){
System.out.println("储存信息是:name="+name+"balance="+balance+"mima="+mima);
}
}
6.封装与构造器:
使用方法:将构造器与set结合:将set放进构造器里面;
eg:
java
public Person(String name,int age,double salary,Stringb job){//构造器
this.setName(name);
this.setAge(age); //this.也可以去掉(当方法中没有局部变量时)
this.setSalary(salary);
this.setJob(job);
}
2.继承:
1.继承使用背景:
解决代码的重复性;
2.介绍:
当多个类中存在相同的属性(变量)和方法时,可以从这些类中抽出父类,在父类定义这些相同的属性和方法,而子类无需再定义这些相同的属性和方法,只需通过extends继承父类即可;
3.继承基本语法:
java
class 子类 extends父类{
}
eg:public Student extends Person{
}
4.继承细节
细节1.
子类继承父类所有的属性和方法,非私有的属性和方法可以在子类中直接访问·,但是私有的属性和方法不能在子类直接访问,要通过父类提供public的方法来访问,之后再在子类中调用该方法;
java
eg:
public class base {//父类
public String name="kk";
private int age=100; //细节1
public int getAge(){//父类提供的public方法供子类访问调用!!!
return age;
}
package com.sjh.ExtendDetail;
//子类;
public class sub extends base{
public void f() {
//System.out.println(name+age);1.子类不可以直接访问父类的非私有属性;
//因为·age是private,所以需要通过父类提供public方法;
System.out.println("age="+getAge());//调用父类提供的public方法:getAge来访问私有属性age;
}
细节2:
子类必须先调用父类的构造器完成父类的初始化;
细节3:
当创建子类对象时不管使用子类的哪个构造器默认情况下都会调用父类的无参构造器,如果父类没有提供无参构造器,则必须在子类构造器中使用super去指定调用父类哪个构造器来完成对父类初始化,否则编译不会通过;
java
package com.sjh.ExtendDetail;
//父类!!!!!
public class base {
public String name="kk";
private int age=100; //细节1
public int getAge(){//父类提供的public方法供子类访问调用
return age;
}
public base (){//父类无参构造器1 //如果父类中的无参构造器没有被删掉,
//则会默认执行无参构造器,而不会执行构造器2!!!!!!!!
System.out.println("base1()...");
}
public base(String name){//父类有参构造器2
System.out.println("base2().....");
}
//细节4:
public base(int age){//父类有参构造器3
System.out.println("base()3.....");
}
}
package com.sjh.ExtendDetail;
//子类;
public class sub extends base{
public void f() {
//System.out.println(name+age);1.子类不可以直接访问父类的非私有属性;
System.out.println("age="+getAge());
}
//需要通过父类提供public方法;
//2.3.
public sub (){//子类无参构造器1
super("ji"); //如果父类的无参构造器被其它构造器覆盖,
// 则必须在子类中所有构造器中先用super指定调用父类的那个构造器;
System.out.println("sub1()...");
}
public sub(String name){//子类有参构造器2
super("kk");//如果父类的无参构造器被其它构造器覆盖,
// 则必须在子类中所有构造器中先用super指定调用父类的那个构造器;
System.out.println("sub2()....");
}
public sub(int age,int money){
super();//意思是调用父类中的无参构造器!!!!!!
System.out.println("sub()3....");
}
}
package com.sjh.ExtendDetail;
public class test {
public static void main(String[]ages){
//细节2:子类必须调用父类的构造器,完成父类的初始化;!!!
System.out.println("-------第一个对象-------");
sub sub1=new sub();
//输出结果:先父类:base()...,后子类:sub()...!!!
//3.细节3:
System.out.println("-------第二个对象-------");
sub sub2=new sub();
细节4:
如果仍希望调用父类中的无参构造器则需要使用super();或者也可以不写因为系统会默认有super();
细节5:
super();必须放在!构造器!的第一行;
细节6:
由于super();,this();都只能放在构造器的!!!第一行,所以不可以同时使用;
细节7:
java中的所有类都是Object类的子类;
细节8:
父类构造器调用不只会继承自己的父类,会一直往上追溯知道Object类;
java
public class xijie8a {
public xijie8a() {//基类无参构造器:会传给下一级的父类构造器:xijie8b
System.out.println("xijie8a()...");
}
}
package com.sjh.ExtendDetail;
public class xijie8b extends xijie8a {//第二级父类无参构造器:会传给下一级
public xijie8b(){
System.out.println("xijie8b()...");
}
}
package com.sjh.ExtendDetail;
public class xijie8c extends xijie8b{//前边两个父类构造器都会传给它
public xijie8c(){
System.out.println("xijie8c()....");
}
}
package com.sjh.ExtendDetail;
//在test方法中测试
public class xijie8test extends xijie8c {
public static void main(String[]ages){
xijie8test a=new xijie8test();//调用构造器了相当于,因为是无参所以创建对象时不用写参数了
}
}
class a{
String name;
}
class b{
String name;
}
细节9:
子类最多只可继承一个父类(指的是:直接继承):java中的单继承机制;
细节10:
不能滥用继承,子类和父类必须满足 is-a逻辑关系;
5.继承原理!!!
根据查找关系返回信息:!!!!!
1.先看子类是否有该属性(方法);
2.如果子类有且可以方法就返回(调用);
3.如果子类没有这个属性(方法),就从父类中查找,如果父类有且可以访问就返回(调用)
4.如果没有就按3.中持续向上查找,直到Objeat类;
5.如果直到Object类都没有找到,或者是不可访问(private)就会报错!!!;
6.练习:
java
1.编写Computer类,包含CPU,内存,硬盘等属性,getdetail方法用于返回Computer的详细信息(基类)
编写pc类,继承Computer类,添加特有属性(品牌:brand)(一级子类)
/编写Notepad子类,添加特有属性(color)(二级子类)
2.在test类中测试
package com.sjh.exercise;
//编写Computer类,包含CPU,内存,硬盘等属性,getdetail方法用于返回Computer的详细信息
public class Computer {
//父类属性;
private String CPU;
private double neicun;
private double yingpan;
public Computer(String CPU,double neicun,double yingpan){ //父类构造器;
this.CPU=CPU;
this.neicun=neicun;
this.yingpan=yingpan;
}
//父类private属性的赋值和返回
public void setCPU(String CPU){
this.CPU=CPU;
}
public String getCPU(){
return CPU;
}
public void setNeicun(double neicun){
this.neicun=neicun;
}
public double getNeicun(){
return neicun;
}
public void setYingpan(double yingpan){
this.yingpan=yingpan;
}
public double getYingpan(){
return yingpan;
}
public void inof(){//输出父类的属性
System.out.println("CPU="+CPU+"neicun="+neicun+"yingpan="+yingpan);
}
// public String info9(){
// return "CPU="+CPU+"neicun="+neicun+"yingpan="+yingpan;
// }//或者改为返回也可以;!!!!!!!!!
}
package com.sjh.exercise;
//编写pc类,继承Computer类,添加特有属性(品牌:brand)
public class Pc extends Computer{//
String brand;
public Pc(String brand){//构造器:初始化对象
super("Intel",34,500);//super调用父类构造器完成父类初始化;
this.brand=brand;//子类特有属性初始化;
}
//get,set:
public void setBrand(String brand){
this.brand=brand;
}
public String getBrand(){
return brand;
}
public void info1(){
System.out.println("brand="+brand);
}
}
package com.sjh.exercise;
//编写Notepad子类,添加特有属性(color)
public class NotePad extends Pc{
//属性
String color;
public NotePad(String color){
super("lenovo");//完成父类初始化;
this.color=color;//初始化color
}
//set,get;
public void setColor(String color){
this.color=color;
}
public String getColor(){
return color;
}
public void info2(){
System.out.println("color="+color);
}
}
package com.sjh.exercise;
public class test {//在test类中测试
public static void main(String[]ages){//main方法
NotePad a =new NotePad("黑色");//只需new子类的对象,因为子类继承了所有父类的属性和方法!!!!
a.inof();
a.info1();
a.info2();
}
}
3.多态
1.多态的前提:
两个对象存在继承关系;
2.类型:
1.属性多态
2.方法多态
3.对象多态!!!
java
package com.sjh.poly.objectpoly;
public class Animal {
public void cry(){
System.out.println("Animal cry()...");
}
}
package com.sjh.poly.objectpoly;
public class Cat0 extends Animal{
public void cry() {
System.out.println("Cat cry()...");
}
}
package com.sjh.poly.objectpoly;
public class Dog extends Animal {
public void cry(){
System.out.println("Dog cry()...");
}
}
package com.sjh.poly.objectpoly;
import com.sjh.poly.Cat;
public class polyobject {
//体验对象多态的特点!!!!!!!!!
public static void main(String[]ages){
Animal animal=new Dog();//披着羊皮的狼!!!
//Animal是编译类型,Dog是运行类型;
animal.cry();//执行到该行时,animal的运行类型是Dog,所以cry就是Dog的cry
animal=new Cat0();
animal.cry();//执行运行时看堆里面的!!!
//所以animal对象是多种状态-》:多态
}
}
3.向上转型:
1.本质:父类的引用指向子类的对象:
2.语法:
ini
语法::Animal animal=new Cat();
Animal:编译类型
Cat:运行类型
3.特点:
1.可以调用父类中所有成员(需要遵守访问权限)
2.但不能调用子类中的特有成员;
3.最终运行效果要看运行类型的具体实现(遵循查找规则);
java
package com.sjh.poly.details;
public class Animal {//父类!
public void n(){
System.out.println("pao");
}
public void n1(){
System.out.println("chang");
}
public void n2(){
System.out.println("tiao");
}
public void n3(){
System.out.println("rap");
}
public void n4(){
System.out.println("lanqiu");
}
}
```mermaid
erDiagram
CUSTOMER ||--o{ ORDER : places
ORDER ||--|{ LINE-ITEM : contains
CUSTOMER }|..|{ DELIVERY-ADDRESS : uses
package com.sjh.poly.details;
public class Cat1 extends Animal {//子类 public void n2(){ System.out.println("jijijijiji"); } public void m(){ System.out.println("niganma"); } public void m1(){ System.out.println("jinitaimei"); } }
package com.sjh.poly.details;
import com.sjh.poly.Cat;
public class test { public static void main(String[]ages){ Animal animal =new Cat1(); //1.可以调用父类所有的成员;但需要遵守访问权限; animal.n2(); animal.n(); animal.n1(); animal.n3(); animal.n4(); //2.但不可以调用子类的特有成员:如Cat中的m,m1方法!! //3.最终运行效果看运行类的具体体现,即调用方法时从运行类开始查找...遵循查找原则 //比如1.:animal.n2(); :构成了方法重写,即先会在Cat类查找,如果有且可以访问就访问它(就近原则) //必然2:animal.n(); :先从运行类型Cat中寻找,但没有,所以会从父类Animal类中找!!!!!!! }
}
shell
### 4.向下转型:
#### 1.介绍:
用于实现调用子类特有成员;
#### 2.语法:
子类类型 引用名=(子类类型)父类引用 eg:Cat cat=(Cat)animal; "="左边:编译类型,右边:运行类型 ->:这里都是Cat类型;
scss
#### 3.要求:
原来父类的引用必须指向当前类型的对象!!!
```java
//多态向下转型:可以调用子类成员
父类子类代码同向上转型例子!!!
Cat1 cat=(Cat1) animal;
((Cat1) animal).m1();//Cat中的m,m1方法可以调用了!!!!
//现在Cat是编译类型,所以可以调用m,m1
//Cat也是运行类型,所以会先从cat开始查找
}
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> </math>