Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

Android Build a Simple Android App Basic Android Programming Accessing Views in Code: Assigning Variables

Matthew Francis
Matthew Francis
6,967 Points

Type Casting clarificaiton

In

 mFactTextView = (TextView) findViewById(R.id.factTextView); /*this returns a view, hence it needs to be upcasted*/

TextView extends View, so View is the parent of TextView

https://developer.android.com/reference/android/widget/TextView.html

So, isnt this downcasting? you are downcasting View to TextView, but by that logic it wouldnt work since you cannot downcast a parent.

Can soemone clarify what is actually happening in the code? what does the cast signify?"

2 Answers

Hi Matthew,

Imagine you have an Animal and a Dog class which extends the latter.

class Animal 
{ 
    public String greeting = "Hi, I am an Animal";
}


class Dog extends Animal 
{ 
    public Dog() {
        greeting = "Hi, I am a Dog";
    }
}

If you cast a Dog to an animal, it's an upcast.

Dog dog1 = new Dog();      
Animal animal1 = (Animal)dog1;

Downcasting works the same, but only if you already know, that the Animal you are casting is a dog.

//Works
Animal animal2 = new Dog();
Dog dog2 = (Dog) animal;

Otherwise, you'll get a ClassCastException:

//Throws a ClassCastException
Animal animal3 = new Animal();
Dog dog3 = (Dog) animal;

It's the same here with View and TextView. Although findViewById() (always) returns a View, it's in fact a TextView, who is just waiting to be casted down.

I hope I clarified it a bit. If you are still confused about the difference, please do not hesitate to ask me again in the comments!

Best Regards, Philip

Source: StackOverflow

Matthew Francis
Matthew Francis
6,967 Points

Ahhh, findViewById() automatically upcasts everything to view, correct?

Yeah, kind of. In fact it's a function with a return type of view, which just returns the text view. I think the compiler does the upcasting automatically. To stay at our example:

public Animal findAnimalById() 
{
    return new Dog();
}
Matthew Francis
Matthew Francis
6,967 Points

Thanks! one more thing...

Why do you have to downcast it again and not leave it as a View to be able to set a property for it?

eg;

Why cant you do this:

findViewById(R.id.relativeView).setBackgroundColor(COLOR.RED);

Instead of

RelativeLayout  relativelayout = (RelativeLayout) findViewById(R.id.factTextView);
relativelayout.setBackGroundColor(COLOR.RED);

The View Class has no setBackgroundColor() method. Upcasting goes automatically while downcasting doesn't. The compiler doesn't know that the View is, in fact, a RelativeView. Example:

class Animal 
{ 
    public String greeting = "Hi, I am an Animal";
}


class Dog extends Animal 
{ 
    public Dog() {
        greeting = "Hi, I am a Dog";
    }
    public String Bark() {
        return "Woof!";
    }
}

class Cat extends Animal 
{ 
    public Cat() {
        greeting = "Hi, I am a Cat";
    }
    public String Meow() {
        return "Meow!";
    }
}

Animal pet = new Cat();

// Compiler doesn't know if it's a Cat or a Dog
pet.Meow();
Matthew Francis
Matthew Francis
6,967 Points

The View Class has no setBackgroundColor() method

Hmm, if you press ctrl + f and search for setBackGroundColor() in:

https://developer.android.com/reference/android/view/View.html

the setBackGroundColor() method is in the Views class(I think?), but by that logic you don't need to downcast it, getting the id itself is enough.

I'm pretty sure I am misunderstanding this, could you clear my thoughts?

Well, my bad :) When I wrote the answer, I haven't really looked up if the View class in fact has a setBackgroundColor Method. At the moment, I don't have a Computer with Android Studio available(holidays :), so could you send me the whole Code you tried?

In theory, you are right, it should work.

class Animal 
{ 
    public String greeting = "Hi, I am an Animal";
    public String Speak() {
      return "I don't yet know how to speak";
    }
}


class Dog extends Animal 
{ 
    public Dog() {
        greeting = "Hi, I am a Dog";
    }
    public String Speak() {
        return "Woof!";
    }
}

class Cat extends Animal 
{ 
    public Cat() {
        greeting = "Hi, I am a Cat";
    }
    public String Speak() {
        return "Meow!";
    }
}

Animal pet = new Cat();

System.out.println(pet.Speak()); // prints "Hi, I am a Cat"

However, it can be that this is a foible of Android. Maybe in some cases, findViewById returns some kind of view. Could you try if this code works?

((View)findViewById(R.id.relativeView)).setBackgroundColor(COLOR.RED);

I'm sorry, but up to now I have always casted the output of findViewById() to the corresponding type. But this is good that this question came up, as we both can learn from it :)

Best Regards, Philip

P.S.: Maybe I'm totally missing something, and Ben Deitch or Ben Jakuben can clear this up?

Adam Sawicki
Adam Sawicki
15,967 Points
 TextView mFactTextView = (TextView) findViewById(R.id.factTextView); /*this returns a view, hence it needs to be upcasted*/

This code means that in variable mTextView type TextView, we want assign obect TextView that represents widget in layout. We can accomplish this by using method findViewById which returns object of type View which as you noticed is general class for all views. Since you know what specific type of object your view is , you can downcast type View to this type of object and everything will be fine, you will receive object of proper type.