整理知识笔记(4)--继承、接口、抽象类

1:重载与覆盖:

重载:不同参数,相同函数名

相同的范围(同一个类中);

函数名字相同;

参数不同(返回值可以不同);

Virtual关键字可有可无;

 

覆盖:派生类中重新定义的函数,其函数名、参数、返回值类型都必须与父类相同。派生类会自动调用子类的覆盖版本。

    不同的范围(分别位于派生类与基类);

    函数名字相同;

    参数相同,返回值必须相同;

    基类函数必须有virtual关键字;

(静态的方法不能被覆盖)

2:

继承结构中,父类的内部细节对子类是可见的,通过继承的代码复用是一种“白盒式代码复用”;

组合是通过对现有的对象进行组合产生新的更复杂的功能,因为在对象之间各自的内部细节是不可见得,所以这种方式叫做“黑盒式代码复用”

 

3:

public class NULL{

public static void main(String[] args){

Father f = new Father();

Father c = new Child();

System.out.println(f.getName()+" "+c.getName());

}

}

class Father{

public static String getName(){

return "Father";

}

}

class Child extends Father{

public static String getName(){

return "Child";

}

}

因为这两个getName方法都是静态方法,所以在内存中的地址空间是固定的,根本不存在冲突问题,他两占用不同的内存空间

执行哪个就要看是由哪个类调用的,因为是静态方法而且两个引用都是father的所有只会调用father的

结果为Father  Father

 

如果都不是staic静态的,就会输出Father  Child

 

静态的就看左边的类   不是静态的就看右边的new

 

Child b = new Child();

Father a =(Father) b;

System.out.println(a.getName());

///输出为Child   因为b是child类所以输出的是child

 

 

 

 

4:super

子类构造函数如果要引用super,就必须把super放在函数的首位,(不可调换顺序)即:

class Checket extends Base{

Checket(){

super();System.out.println("Checket");

}

}

如果不放在第一行的话,那么最后使用了super继承父类的构造方法,那么就又重新回到父类的构造方法,与子类无关。

 

当子类的成员变量或方法与父类中的成员变量或方法同名时,因为子类的优先级高,所以子类的成员变量或方法就会隐藏父类的成员变量和方法,当需要使用父类的成员变量或方法时就需要super。

 

5:this   (输出结果为test   hello)

public class NULL{

public static void main(String[] args){

Test t = new Test(5);///第1步,先执行Test(int var)

}

}

class Test{

int var;

Test(int var){

this("hello");///第2步,执行Test(String s)

}

Test(String s){

this();///第3步,执行Test(),输出test

System.out.println(s);///第4步,输出S:hello

}

Test(){

System.out.println("test");

}

}

 

6:this  和  super

This关键字使用在一个成员函数的内部,指向当前对象(即调用当前正在执行方法的那个对象);

Super关键字是直接执行超类的构造函数,用来引用超类的中的变量和方法。(使用this三种方法:)

this.name;//使用this访问成员变量以区分同名参数

System.out.println(this);///可以直接打印出固有参数的当前状态

this(name,age);///写于构造函数的第一个语句,进行赋值

7:

public class NULL{

public static void main(String[] args){

go(new mybase());

}

static void go(base b){///第7步

b.add(8);///相当于base b = new mybase()  成员函数看mybase  6+8*2=22

}

}

class base{

int i;

base(){

add(1);///第一步,调用mybase的add(1)

System.out.println(i);///第3步::输出2

}

void add(int v){

i+=v;    System.out.println(i);

}

}

class mybase extends base{

mybase(){

add(2);///第4步:

System.out.println(i);///第6步::输出6

}

void add(int v){

i+=v*2;///第2步i=0+1*2=2;;;第5步:i=2+2*2

System.out.println(i);///第2步:输出2;;;;第5步:输出6

}

}

在主函数中,首先执行new mybase(),子类会先调用父类的构造函数;父类的构造函数base()中执行add()方法

 

这个add()方法由于是在新建mybase对象是调用,将会先查找mybase有无此方法,所以base()中的add(1)实际是:

(即当前对象的add方法)

void add(int v){

i+=v*2;///i=0+1*2

System.out.println(i);//输出2

}

 

输出结果为2 2 6 6 22

 

8:抽象类与接口

C++没有对抽象类进行直接声明的方法,而认为只要在类中定义了纯虚函数,此类即为抽象类

///C++中定义抽象类的做法

class shape{///此处不需要显示的声明抽象类

public :

shape(){}

~shape(){}

virtual void draw()=0;///定义了纯虚函数

}

Java是通过显式的声明抽象类并使用abstract修饰符的方法

///java中定义抽象类的做法

abstract class shape{///此处显示声明抽象类

public abstract void find();

public void about(){

System.out.println("abstract");

}

}

 

抽象类:

1)抽象类只能作为其他类的基类,它不能被实例化,而且不能使用new操作符。抽象类如果含有抽象的变量或值,则他们要么是null类型,要么包含了对抽象类的实例的引用;

2)抽象类允许包含抽象成员,但这不是必须的,也可以没有任何抽象成员;抽象类可以有非抽象方法;(即空的抽象类也是可以的)

3)抽象类不能同时又是final,抽象类希望被继承,final类希望不被继承;

4)如果一个非抽象类从抽象类派生,就必须通过覆盖来实现所有继承来的抽象成员;(覆盖:派生类中重新定义函数)

5)抽象类可以被抽象类继承,就够然为抽象类

6)抽象类可以被声明

如下面一段程序:

abstract class person{///建立抽象类

public abstract void say();//抽象方法

public void about(){//非抽象方法

System.out.println("abstract");

}

}

 

class student extends person{

//建立实体类student继承抽象类person

public void say(){//子类覆盖抽象方法say

System.out.println("stu say");

}

}

class nurse extends person{

///没有覆盖抽象类方法say,所以这个类是错误

}

 

abstract class pupli extends person{

//建立抽象类pupli 继承抽象类person

public void say(){//抽象子类覆盖say

System.out.println("pup say");

}

}

abstract class worker extends person{

//建立抽象类worker继承person

//抽象类继承抽象类,可以不覆盖say,所以此类正确

}

 

9:接口:(public  abstract方法   static变量  无构造方法  final变量 

1)接口用于描述系统外提供的所有服务,因为接口中的成员变量和方法都必须是public类型的,确保外部使用者都可以访问他们;

2)接口仅仅描述系统能够做什么,但不指明如何去做,所以接口中的方法都是抽象abstract方法

3)接口不涉及任何与实例相关的细节,因此接口没有构造方法,不能被实例化,没有实例变量,只有static变量

4)接口中的变量是所有实现类共有的,既共有就不可变,所以变量是不可变类型(final),即常量;即接口中不存在变量

5)接口只是对一类事务的属性和行为更高层的抽象,对修改关闭,对implement开发;接口的方法默认是public abstract ,接口的属性默认为public static final常量,且必赋初值

注意:final与abstract不可同时出现;

开发人员能够分工明确,只要确定下来接口了,就可以同时进行开发,提高开发效率。另外,使用接口还有使用方便,可读性强,结构清晰、方便维护等优点。
定义一个接口,可以有多种实现。变量声明为接口变量,调用接口方法,以后切换实现类的时候,原有代码不用修改。
解耦,可扩展这是设计接口的主要原因之一
为什么接口可以多继承,而类不可以?
如果有两个父类,两个父类里有一个相同的方法,那么作为子类应该怎么继承这个方法?父类1的还是父类2的?
但是实现多个接口则没问题,因为不管哪个接口,调用的都是同一个实现,因为只有方法名!
而且单继承的目的之一,就是降低复杂度,减少维护难度
继承:描述事物的自然属性和行为的复用。
接口:描述事物的社会属性和行为的复用。
class 负责实现, interface负责接口;

class 负责实现, interface负责接口;多继承最麻烦的问题就是冲突, 冲突主要体现在 实现的时序和传入参数, 传出参数这几个方面对于实现来说,父类发生时序问题时,使得语言本身变得无比复杂,而多继承问题在实现本身是可以通过很多方式解决的, 而对于接口来说,传入参数冲突是overload,则不是问题, 只有传出参数这个问题是接口多继承不允许的例如:
public interface IA {
void doSomething();
}
public interface IB {
Integer doSomething();
}
public interface IAB extends IA, IB {
@Override 
public void doSomething();
@Override 
public Integer doSomething();
}
这种情况编译器会告诉你, IA, IB 接口冲突,是不允许的

参考https://www.cnblogs.com/yunxiblog/p/5240690.html

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值