Java에서 클래스 변수를 덮어쓰는 방법이 있나요?
class Dad
{
protected static String me = "dad";
public void printMe()
{
System.out.println(me);
}
}
class Son extends Dad
{
protected static String me = "son";
}
public void doIt()
{
new Son().printMe();
}
"do" 함수는 "dad"를 인쇄합니다."아들"로 출력할 수 있는 방법이 있나요?
즉, 클래스 변수를 덮어쓸 방법은 없습니다.
Java에서는 클래스 변수를 덮어쓰지 않고 숨깁니다.덮어쓰기는 인스턴스 메서드에 대한 것입니다.숨김은 덮어쓰기와는 다릅니다.
앞에서 설명한 예에서는 클래스 변수를 클래스 Son의 이름 'me'로 선언함으로써 같은 이름의 슈퍼 클래스 Dad로부터 상속받은 클래스 변수를 숨깁니다.이 방법으로 변수를 숨겨도 슈퍼클래스 Dad의 클래스 변수 'me' 값에는 영향을 주지 않습니다.
질문의 두 번째 부분인 "아들"을 인쇄하는 방법은 컨스트럭터를 통해 값을 설정합니다.아래 코드는 당신의 원래 질문에서 많이 벗어나지만, 저는 이렇게 쓰고 싶습니다.
public class Person {
private String name;
public Person(String name) {
this.name = name;
}
public void printName() {
System.out.println(name);
}
}
JLS는 섹션 8.3 - Field Declarations에서 숨기는 방법에 대해 자세히 설명합니다.
예. 그러나 변수와 관련하여 덮어쓰기(변수에 새 값 부여)입니다.함수에 새로운 정의를 부여하면 덮어쓰기입니다.변수를 선언하지 말고 생성자 또는 정적 블록에서 초기화(변경)하면 됩니다.
부모 클래스의 블록에서 사용할 때 값이 반영됩니다.
변수가 static일 경우 초기화 중에 static block으로 값을 변경합니다.
class Son extends Dad {
static {
me = "son";
}
}
그렇지 않으면 컨스트럭터가 변경됩니다.
나중에 임의의 블록에서 값을 변경할 수도 있습니다.슈퍼클래스에 반영될 것이다.
,, 냥, 냥, 그, 그, the, the, the, the, the, the, .printMe()
★★★★
class Son extends Dad {
public static final String me = "son";
@Override
public void printMe() {
System.out.println(me);
}
}
getter를 수 .재정의할 변수가 하위 클래스인 경우 특히 유용합니다.에 신신 has has imagine imagine가 있다고 상상해 보세요.Object
에서는 이 이 더 .Integer
.
class Dad
{
private static final String me = "dad";
protected String getMe() {
return me;
}
public void printMe()
{
System.out.println(getMe());
}
}
class Son extends Dad
{
private static final String me = "son";
@Override
protected String getMe() {
return me;
}
}
public void doIt()
{
new Son().printMe(); //Prints "son"
}
덮어쓸 경우 이 상태를 유지할 타당한 이유를 찾을 수 없습니다.추상화의 사용을 제안합니다(예 코드 참조).:
public interface Person {
public abstract String getName();
//this will be different for each person, so no need to make it concrete
public abstract void setName(String name);
}
이제 아버지를 추가할 수 있습니다.
public class Dad implements Person {
private String name;
public Dad(String name) {
setName(name);
}
@Override
public final String getName() {
return name;
}
@Override
public final void setName(String name) {
this.name = name;
}
}
아들:
public class Son implements Person {
private String name;
public Son(String name) {
setName(name);
}
@Override
public final String getName() {
return name;
}
@Override
public final void setName(String name) {
this.name = name;
}
}
아빠는 멋진 아가씨를 만났어
public class StepMom implements Person {
private String name;
public StepMom(String name) {
setName(name);
}
@Override
public final String getName() {
return name;
}
@Override
public final void setName(String name) {
this.name = name;
}
}
우리에겐 가족이 있는 것 같은데 세상에 이름을 알리자
public class ConsoleGUI {
public static void main(String[] args) {
List<Person> family = new ArrayList<Person>();
family.add(new Son("Tommy"));
family.add(new StepMom("Nancy"));
family.add(new Dad("Dad"));
for (Person person : family) {
//using the getName vs printName lets the caller, in this case the
//ConsoleGUI determine versus being forced to output through the console.
System.out.print(person.getName() + " ");
System.err.print(person.getName() + " ");
JOptionPane.showMessageDialog(null, person.getName());
}
}
}
: Dad 시스템.out 력 : Tommy Nancy Dad
System.errr system system(((((( ( 색 system system system system system system system system system system 。
JOPtion 력: :
그럼 토미
그럼 낸시
Dad아빠.
설계상의 결함인 것 같습니다.
static 키워드를 삭제하고 예를 들어 컨스트럭터에서 변수를 설정합니다.이렇게 하면 Son은 생성자에서 변수를 다른 값으로 설정할 수 있습니다.
있으나 클래스 변수만 서브 클래스에서 재정의되지 숨길 것이 사실이라면, 여전히 너가 원하클래스를 재정의하지 않고서 하는 것 변수가 덮어쓰지 않고 하위 클래스에서만 숨길 수 있는 것은 사실이지만 덮어쓰지 않고 원하는 작업을 수행할 수 있습니다 가능하다.printMe ()
에서 서브 클래스,와 반성이란 당신의 친구입니다.그리고반성은 당신의 친구입니다.이 코드에서는 아래 나는 명확성을 위해 예외 처리 사항을 빠뜨리다아래 코드에서는 알기 쉽게 예외 처리를 생략합니다.참고로 선언 선언하는것에 주의해 주세요.me
~하듯이로protected
그것의 하위 분류에 숨길 것이다 이 맥락에서 이해되는 것은 많는 것을 꺼리지 않나...하위 분류에 숨겨질 것이기 때문에 이 맥락에서 별로 의미가 없어 보인다.
class Dad
{
static String me = "dad";
public void printMe ()
{
java.lang.reflect.Field field = this.getClass ().getDeclaredField ("me");
System.out.println (field.get (null));
}
}
https://docs.oracle.com/javase/tutorial/java/IandI/hidevariables.html
필드 숨기기라고 합니다.
위 링크에서
클래스 내에서 슈퍼클래스의 필드와 이름이 같은 필드는 유형이 다르더라도 슈퍼클래스의 필드를 숨깁니다.하위 클래스 내에서 슈퍼 클래스의 필드는 단순 이름으로 참조할 수 없습니다.대신 다음 섹션에서 설명하는 super를 통해 필드에 액세스해야 합니다.일반적으로 필드를 숨기는 것은 코드를 읽기 어렵기 때문에 권장하지 않습니다.
class Dad
{
protected static String me = "dad";
public void printMe()
{
System.out.println(me);
}
}
class Son extends Dad
{
protected static String _me = me = "son";
}
public void doIt()
{
new Son().printMe();
}
...가 "아들"을 인쇄합니다.
필드가 덮어쓰기되지 않고 숨겨져 있기 때문에 실제로 'dad'로 표시됩니다.'아들'을 인쇄하려면 세 가지 방법이 있습니다.
접근법 1: print Me 덮어쓰기
class Dad
{
protected static String me = "dad";
public void printMe()
{
System.out.println(me);
}
}
class Son extends Dad
{
protected static String me = "son";
@override
public void printMe()
{
System.out.println(me);
}
}
public void doIt()
{
new Son().printMe();
}
접근법 2: 필드를 숨기지 않고 컨스트럭터에서 초기화합니다.
class Dad
{
protected static String me = "dad";
public void printMe()
{
System.out.println(me);
}
}
class Son extends Dad
{
public Son()
{
me = "son";
}
}
public void doIt()
{
new Son().printMe();
}
접근법 3: 정적 값을 사용하여 생성자의 필드를 초기화합니다.
class Dad
{
private static String meInit = "Dad";
protected String me;
public Dad()
{
me = meInit;
}
public void printMe()
{
System.out.println(me);
}
}
class Son extends Dad
{
private static String meInit = "son";
public Son()
{
me = meInit;
}
}
public void doIt()
{
new Son().printMe();
}
변수는 재정의에 관여하지 않습니다.방법만이 가능하다.메서드 호출은 런타임에 해결됩니다.즉, 메서드 호출 결정은 런타임에 이루어지지만 변수는 컴파일 시에만 결정됩니다.따라서 이 변수는 런타임오브젝트가 아닌 호출에 사용되는 참조 변수입니다.
다음 토막을 참조하십시오.
package com.demo;
class Bike {
int max_speed = 90;
public void disp_speed() {
System.out.println("Inside bike");
}
}
public class Honda_bikes extends Bike {
int max_speed = 150;
public void disp_speed() {
System.out.println("Inside Honda");
}
public static void main(String[] args) {
Honda_bikes obj1 = new Honda_bikes();
Bike obj2 = new Honda_bikes();
Bike obj3 = new Bike();
obj1.disp_speed();
obj2.disp_speed();
obj3.disp_speed();
System.out.println("Max_Speed = " + obj1.max_speed);
System.out.println("Max_Speed = " + obj2.max_speed);
System.out.println("Max_Speed = " + obj3.max_speed);
}
}
코드를 실행하면 콘솔에 다음과 같이 표시됩니다.
Inside Honda
Inside Honda
Inside bike
Max_Speed = 150
Max_Speed = 90
Max_Speed = 90
오직 덮어쓰기만을 재정의함으로써 하면printMe()
:
class Son extends Dad
{
public void printMe()
{
System.out.println("son");
}
}
에대한 언급에 대한 참조를me
그 에서에Dad.printMe
방법 암시적으로 정적 필드에 메서드는 암묵적으로정적 필드를 가리킵니다 지적하고 있다.Dad.me
, 그래서 하나의 방법 또는 다른 무슨 그래서 어떻게 해서든 당신이 바꿀 수 있는 것은 바꿀 것이다.printMe
에서 한다에Son
클래스의 변수를 재정의할 수 없습니다.메서드만 재정의할 수 있습니다.변수를 비공개로 유지해야 합니다. 그렇지 않으면 많은 문제가 발생할 수 있습니다.
아니요. 클래스 변수(인스턴스 변수에도 적용 가능)는 호출 객체의 유형에 따라 클래스 변수가 호출되므로 Java에서 우선 기능을 나타내지 않습니다.보다 명확하게 하기 위해 계층에 클래스(인간)를 하나 더 추가했습니다.이제 우리는
아들은 아버지가 인간을 확장한다.
다음 코드에서는 Human, Dad 및 Son 오브젝트 배열에 대해 반복 시도하지만 호출 오브젝트의 유형이 Human이었기 때문에 모든 경우에 Human Class 값이 출력됩니다.
class Human
{
static String me = "human";
public void printMe()
{
System.out.println(me);
}
}
class Dad extends Human
{
static String me = "dad";
}
class Son extends Dad
{
static String me = "son";
}
public class ClassVariables {
public static void main(String[] abc) {
Human[] humans = new Human[3];
humans[0] = new Human();
humans[1] = new Dad();
humans[2] = new Son();
for(Human human: humans) {
System.out.println(human.me); // prints human for all objects
}
}
}
인쇄하다
- 인간적인
- 인간적인
- 인간적인
따라서 클래스 변수를 재정의하지 않습니다.
부모 클래스의 참조 변수에서 실제 객체의 클래스 변수에 액세스하려면 부모 참조(Human object)를 해당 유형에 캐스팅하여 컴파일러에 명시적으로 알려야 합니다.
System.out.println(((Dad)humans[1]).me); // prints dad
System.out.println(((Son)humans[2]).me); // prints son
인쇄하다
- 아빠.
- 아들.
이 질문의 일부에 대해서:- 이미 제시된 바와 같이 Son 클래스의 print Me() 메서드를 덮어쓴 후 호출 시
Son().printMe();
Dad's Class 변수 "me"는 "me" (Son class printme) 메서드에서 가장 가까운 선언이 우선되므로 숨겨집니다.
하위 클래스 컨스트럭터의 Super.variable을 호출합니다.
public abstract class Beverage {
int cost;
int getCost() {
return cost;
}
}`
public class Coffee extends Beverage {
int cost = 10;
Coffee(){
super.cost = cost;
}
}`
public class Driver {
public static void main(String[] args) {
Beverage coffee = new Coffee();
System.out.println(coffee.getCost());
}
}
출력은 10 입니다.
물론 개인 속성, getter 및 setter를 사용하는 것이 권장됩니다만, 다음의 테스트를 실시했습니다만, 효과가 있습니다.코드의 코멘트를 참조해 주세요.
class Dad
{
protected static String me = "dad";
public void printMe()
{
System.out.println(me);
}
}
class Son extends Dad
{
protected static String me = "son";
/*
Adding Method printMe() to this class, outputs son
even though Attribute me from class Dad can apparently not be overridden
*/
public void printMe()
{
System.out.println(me);
}
}
class Tester
{
public static void main(String[] arg)
{
new Son().printMe();
}
}
제가 상속의 규칙을 재정의한 건가요, 아니면 오라클을 곤란한 상황에 빠뜨린 건가요?이 프로그램을 실행하면 알 수 있듯이 보호된 스태틱 String me는 명확하게 덮어씁니다.또한 속성을 덮어쓸 수 없는 이유를 알 수 없습니다.
하위 클래스에서 변수를 쉽게 재할당할 수 있는데 변수를 재정의하려는 이유는 무엇입니까?
저는 언어 디자인에 대한 작업을 하기 위해 이 패턴을 따릅니다.프레임워크에 중량감 있는 서비스 클래스가 있으며, 여러 파생 애플리케이션에서 다른 맛으로 사용해야 한다고 가정합니다.이 경우 슈퍼클래스 로직을 설정하는 가장 좋은 방법은 '정의' 변수를 재할당하는 것입니다.
public interface ExtensibleService{
void init();
}
public class WeightyLogicService implements ExtensibleService{
private String directoryPath="c:\hello";
public void doLogic(){
//never forget to call init() before invocation or build safeguards
init();
//some logic goes here
}
public void init(){}
}
public class WeightyLogicService_myAdaptation extends WeightyLogicService {
@Override
public void init(){
directoryPath="c:\my_hello";
}
}
언급URL : https://stackoverflow.com/questions/685300/is-there-a-way-to-override-class-variables-in-java
'IT이야기' 카테고리의 다른 글
Vuejs 검색 필터 (0) | 2022.05.27 |
---|---|
2개의 Java 8 스트림 또는 스트림에 추가 요소 추가 (0) | 2022.05.27 |
C 프로그램에서 날짜와 시간 값을 얻는 방법은 무엇입니까? (0) | 2022.05.27 |
IntelliJ IDEA가 인터페이스에서 Java 구현 클래스로의 도약 (0) | 2022.05.27 |
__DA 사용방법TE__와 __TIME__의 매크로가 2개의 정수로 정의되어 있습니다.그러면 스트링화? (0) | 2022.05.27 |