在基类型" virtual
"中声明方法然后使用" override
"关键字在子类型中覆盖它而不是new
在声明子类型中的匹配方法时简单地使用" "关键字之间有什么区别?
我有一个名称隐藏问题,这是一个非常难以解决的问题.这是一个解释问题的简化版本:
有一节课: org.A
package org;
public class A{
public class X{...}
...
protected int net;
}
Run Code Online (Sandbox Code Playgroud)
然后是一堂课 net.foo.X
package net.foo;
public class X{
public static void doSomething();
}
Run Code Online (Sandbox Code Playgroud)
而现在,这是一个有问题的类,它继承A
并且想要调用net.foo.X.doSomething()
package com.bar;
class B extends A {
public void doSomething(){
net.foo.X.doSomething(); // doesn't work; package net is hidden by inherited field
X.doSomething(); // doesn't work; type net.foo.X is hidden by inherited X
}
}
Run Code Online (Sandbox Code Playgroud)
如你所见,这是不可能的.我不能使用简单名称,X
因为它被继承的类型隐藏.我无法使用完全限定名称net.foo.X
,因为net
它被继承的字段隐藏.
只有类B
在我的代码库中; 类net.foo.X
和org.A …
任何人都可以在内存和引用方面告诉覆盖和隐藏的工作.
class A
{
public virtual void Test1() { //Impl 1}
public virtual void Test2() { //Impl 2}
}
class B : A
{
public override void Test1() { //Impl 3}
public new void Test2() { Impl 4}
}
static Main()
{
A aa=new B() //This will give memory to B
aa.Test1(); //What happens in terms of memory when this executes
aa.Test2(); //-----------------------SAME------------------------
}
Run Code Online (Sandbox Code Playgroud)
这里的内存是B类,但在第二个语句中,将调用aa.Test2类A的方法.为什么?如果B有内存,则应调用B的方法(在我看来).
任何非常深刻和完全描述这一基础的链接/练习将是一个很大的帮助.
我正在学习C#,我遇到了以下问题.我有两个类:base和derived:
class MyBase
{
public void MyMethod()
{
Console.WriteLine("MyBase::MyMethod()");
}
}
class MyDerived: MyBase
{
public void MyMethod()
{
Console.WriteLine("MyDerived::MyMethod()");
}
}
Run Code Online (Sandbox Code Playgroud)
现在,没有virtual
和override
关键词.当我编译它时,我得到警告(当然是预期的)我试图隐藏MyMethod
在MyBase
课堂上.
我想要做的是从具有派生类实例的基类调用该方法.我是这样做的:
MyDerived myDerived = new MyDerived();
((MyBase)myDerived).MyMethod();
Run Code Online (Sandbox Code Playgroud)
当我没有virtual
在方法中指定任何等关键字时,它工作正常.我试着把关键字组合起来,得到了以下结果:
| MyBase::MyMethod | MyDerived::MyMethod | Result printed on the console |
| -----------------|---------------------|-------------------------------|
| - | - | MyBase::MyMethod() |
| - | new | MyBase::MyMethod() |
| virtual | new | MyBase::MyMethod() |
| virtual | override | …
Run Code Online (Sandbox Code Playgroud) 在类中,与超类中的字段具有相同名称的字段会隐藏超类的字段.
public class Test {
public static void main(String[] args) {
Father father = new Son();
System.out.println(father.i); //why 1?
System.out.println(father.getI()); //2
System.out.println(father.j); //why 10?
System.out.println(father.getJ()); //why 10?
System.out.println();
Son son = new Son();
System.out.println(son.i); //2
System.out.println(son.getI()); //2
System.out.println(son.j); //20
System.out.println(son.getJ()); //why 10?
}
}
class Son extends Father {
int i = 2;
int j = 20;
@Override
public int getI() {
return i;
}
}
class Father {
int i = 1;
int j = 10;
public int getI() …
Run Code Online (Sandbox Code Playgroud) 考虑以下结构层次结构:
struct I1 {
virtual void doit() = 0;
};
struct I2 {
virtual void doit(int) = 0;
};
struct I12 : I1, I2 {
using I1::doit;
using I2::doit;
};
struct Derived : I12 {
void doit(int) override {}
};
Run Code Online (Sandbox Code Playgroud)
编译它(使用clang
或g++
使用-Woverloaded-virtual
)会给我一个警告:
'Derived::doit' hides overloaded virtual function [-Woverloaded-virtual]
Run Code Online (Sandbox Code Playgroud)
但是,如果我更改I12
为以下内容,它会编译得很好clang
,同时g++ -Woverloaded-virtual
仍会发出警告:
struct I12 : I1, I2 {
using I1::doit;
void doit(int) override = 0;
};
Run Code Online (Sandbox Code Playgroud)
using I2::doit
和之间的区别在哪里void doit(int) …
Eclipse有一个名为"字段声明隐藏另一个字段或变量"的java编译器设置,可以设置为警告/错误.
您认为这个警告有多重要?
处理这个问题的标准方法是什么?
发生这种情况的代码示例:
public class Test {
private String caption = null;
public Test(String caption) { // here
this.caption = caption;
}
}
Run Code Online (Sandbox Code Playgroud)
我已经看到了重命名字段的解决方案,即"fCaption",但这会导致可以被生成的自动getter/setter具有奇数名称(getfCaption()
).不难读,但丑陋......
编辑:哦,是的,有可能重命名方法签名Test(String caption_)
或类似的东西,但这将最终在javadoc看起来很奇怪.
偶然地,我发现您可以在没有编译器抱怨的情况下执行此操作:
extension Date {
var timeIntervalSinceNow: TimeInterval {
return 1000
}
}
Run Code Online (Sandbox Code Playgroud)
奇怪的是,这实际上评估为1000:
Date().timeIntervalSinceNow
Run Code Online (Sandbox Code Playgroud)
因此,我尝试在自己的课堂上这样做:
class A {
var a: String {
return "A"
}
}
extension A {
var a: String {
return "a"
}
}
Run Code Online (Sandbox Code Playgroud)
我观察到这不会通过协议影响原始成员的使用,这是预期的隐藏行为:
extension Date {
var description: String {
return "XXXX"
}
}
let date: CustomStringConvertible = Date()
date.description // normal date
Date().description // "XXXX"
Run Code Online (Sandbox Code Playgroud)
您能解释为什么会出现子弹头现象吗?
我有一个带有一些实现方法的抽象超类。
是否可以在继承该超类的子类中隐藏该超类的方法?我不想让某些方法在某些子类中从超类中可见。最后但并非最不重要的一点是,是否可以更改子类中与超类中具有相同名称的方法的参数数量?
假设我们public void test(int a, int b)
在超类中有一个方法,但现在我想public void test(int a)
在子类中有一个方法来调用超类函数,而超类中的方法不再可见。
被调用的重写方法的版本取决于您是否关心“通过”基类或“通过”派生类调用函数。但是,我发现如果我调用一个非重写方法,并且重写方法调用一些被重写的函数,那么基类版本仍然被调用,即使我通过指向派生类的指针访问实例。有人可以解释为什么会发生这种情况吗?
代码:
class Base {
public:
void display() {
foo();
}
void foo() {
cout << "Base.foo()" << endl;
}
};
class Derived : public Base {
public:
void foo() {
cout << "Derived.foo()" << endl;
}
};
int main() {
Derived* derived = new Derived();
derived->display();
while (true) {}
}
Run Code Online (Sandbox Code Playgroud) member-hiding ×10
java ×4
overriding ×4
c# ×3
inheritance ×3
c++ ×2
base ×1
compilation ×1
eclipse ×1
field ×1
methods ×1
name-clash ×1
oop ×1
overloading ×1
polymorphism ×1
swift ×1
syntax ×1
virtual ×1