术语Override,Overload,Hide,Shadow,Obscure的解释

Override,即重写,Java最基础的编程技巧之一。仅针对实例方法,并且能够被子类所访问, 且子类该方法的访问权限至少大于父类。遵循运行期绑定原则。

Overload,即重载,Java最基础的编程技巧之一。要求方法名相同,签名不同(参数类型,参数个数,返回类型等)。遵循编译期绑定原则。

Hide,即隐藏,指实例域,静态方法,成员类型可以分别隐藏继承自超类的可访问的相同名字的实例域,静态方法,成员类型。

Shadow,即遮蔽,指一个变量,方法或类型可以分别遮蔽一个闭合的文本范围内的具有相同名字的所有变量,方法或类型。

Obscure,即遮掩,指一个变量可以遮掩一个相同名字的类型,只要它们在同一个范围内。

重点分析Hide,Shadow,Obscure的区别。

一、Hide存在于子类继承自父类的场景,且子类和父类具有相同名字的实例域,静态方法,成员类型。并且能够隐藏的东西都是父类可以访问到的。且对于静态方法来说,隐藏要求子类该静态方法的访问权限大于等于父类访问权限。

例如:

class Foo {
     public String className = "foo";
     public static void f() {}
     public static class innerClass {
          static String innerName = "FooInner";
     }
}

class Sub extends Foo {
     String className = "sub";
     static void f() {}
     static class innerClass {
          static String innerName = "SubInner";
     }
}

这个案例就是隐藏,但是Sub的f()无法编译通过,因为它的访问权限小于父类。但是实例域或成员类型(Member Type)对于访问权限没有这个限制。

关于成员类型,Oracle官方给了解析,链接: http://docs.oracle.com/javase/specs/jls/se7/html/jls-8.html#jls-8.5。可以看出成员类型大概指内部类或者接口。

二、Shadow存在于一个闭合的范围内,当一个变量与另一个实例域或者对象或者方法同名将发生遮蔽,最常见的两种遮蔽:

1.成员变量名和局部变量名相同,这局部变量所在的范围内,无法访问到成员变量。

2.构造方法的参数名和成员变量名相同,成员变量被遮蔽,这种遮蔽是合法的,也是类初始化有参构造器最常见的写法。

例如:

public class WhoKnows {
     static String sentence = "I don't know.";
     public static void main(String[] args) {
          String sentence = "I know!"; // shadows static field
          System.out.println(sentence); // prints local variable
          
          Belt belt = new Belt(3);
          System.out.println(belt.getSize());
     }
}

class Belt {
     private int size;
     public Belt(int size) { // Parameter shadows Belt.size
          this.size = size;
     }
     public int getSize() {
          return size;
     }
     public void setSize(int size) {
          this.size = size;
     }
}

三、Obscure存在于同一个范围内,一个变量名遮掩另一个相同变量名的类型。

例如:

public class Obscure {
     static String System; // Obscures type java.lang.System
     public static void main(String[ ] args) {
          // Next line won't compile: System refers to static field
          System.out.println("hello, obscure world!");
     }
}

这个例子中System作为一个不规范的变量名遮掩了java.lang.System类,导致了Obscure类中,所有的本该引用java.lang.System的地方都引用了String类型的System,从而导致编译错误。

比较Shadow和Obscure,二者很相似。但是还是有点区别:

1.由Shadow导致的遮蔽通常不会发生编译错误。它只是在一个闭合的文本范围内覆盖了另一个同名的实例。但是由Obscure导致的遮掩却极易导致编译错误,尤其是和Java平台已有的类重名时。

2.遮蔽通常只是覆盖一个实例或方法,而遮掩却覆盖了整个类型。

在C++中,我们可以使用关键字来隐藏、覆盖和重载成员函数。 1. 隐藏(Hide):当派生类中定义了与基类中同名的成员函数时,基类的成员函数将被隐藏。可以使用作用域解析运算符(::)来访问被隐藏的基类成员函数。 ```cpp class Base { public: void foo() { cout << "Base::foo()" << endl; } }; class Derived : public Base { public: void foo() { cout << "Derived::foo()" << endl; } }; int main() { Derived d; d.foo(); // 输出 Derived::foo() d.Base::foo(); // 输出 Base::foo() return 0; } ``` 2. 覆盖(Override):当派生类中定义了与基类中同名、同参数列表的成员函数时,称为覆盖。在派生类对象上调用该函数时,将执行派生类的实现而不是基类的实现。 ```cpp class Base { public: virtual void foo() { cout << "Base::foo()" << endl; } }; class Derived : public Base { public: void foo() override { // 使用 override 关键字显式声明覆盖 cout << "Derived::foo()" << endl; } }; int main() { Derived d; Base* b = &d; b->foo(); // 输出 Derived::foo() return 0; } ``` 3. 重载(Overload):在同一个作用域内,可以定义多个同名函数但参数列表不同,称为重载。编译器根据函数调用时所传递的参数类型和数量来决定调用哪个函数。 ```cpp class MyClass { public: void foo(int x) { cout << "foo(int): " << x << endl; } void foo(double x) { cout << "foo(double): " << x << endl; } }; int main() { MyClass obj; obj.foo(10); // 输出 foo(int): 10 obj.foo(3.14); // 输出 foo(double): 3.14 return 0; } ``` 希望以上解释能够帮助到你!如果你有更多的问题,请继续提问。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Alphathur

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值